An article to understand webpack

An article to understand webpack

This article is written based on

webpack 5

1. Getting started (familiarize yourself with the configuration of webpack)

1.1 Create an engineering project

This will generate a package.json file under the current file

@1 Engineering a project

npm init -y duplicated code

@2 According to official requirements, we download two packages

npm i webpack webpack-cli -D duplicated code
  • Installed in the production environment by default
    production
  • -D installed in the development environment
    development

Webpack is packaged according to dependencies. All installations will eventually be packaged in which environment it is opened. This distinction is just for specification

@3 Create a src in the root directory and create an index.js

@4 Modify package.json

@5 execute

npm run build1 copy the code

At this point, the simple packaging of webpack has been completed, and you will see that one is generated in the root directory.

dist
folder

1.2 Introduction to the core configuration

First of all, we must know that the bottom layer of webpack is written based on express, and express is developed based on nodejs, so we must follow the CommonJS specification in the configuration file webpack.config.js

@1 Create a webpack.config.js

After creating a webpack.config.js in the root directory, we can configure webpack in this file (that is, write rules in webpack)

@2 Export configuration

//@1 Method one module .exports = { } //@2 Method two module .exports = function () { //Here you can use the parameters passed by the arguments command interface console .log( arguments ); return { } } Copy code

How to use the command interface to pass parameters?

Output in method two

@3 Core concepts

Mode

By choice

development
,
production
or
none
One of them, to set
mode
parameter

module .exports = { mode : 'production' , }; Copy code
Entry

Inlet starting point (entry point) indicates which module webpack should be used to build as the internal dependency graph (dependency graph) starts.

webpack will recursively build a *dependency graph*
The packaged files will be analyzed below

An entrance

module .exports = { //No matter where the configuration file is./is the root directory entry : './src/index.js' , }; Copy code

Multiple entrances

 Waiting to write

Output

The output attribute tells webpack where to output the bundles it creates and how to name these files. The default value of the main output file is

./dist/main.js
, Other generated files are placed in
./dist
Folder.

  • path where to put the packaged file
  • filename The name of the packaged file
const path = require ( 'path' ); module .exports = { output : { //Must be an absolute address path : path.resolve(__dirname, 'dist' ), filename : 'mydist, }, }; Copy code
loader

What is loader
?

Let's take a look at what the official Wendan said

webpack can only understand JavaScript and JSON files, which is the built-in capability of webpack available out of the box. loader so webpack able to handle other types of files, and converts them into an effective module for use by application programs, and is added to the dependency graph.

loader evaluates/executes from right to left (or bottom to top)

The following 1.3.2 will explain in detail

Let's take a closer look at the loader through the code

const path = require ( 'path' ); module .exports = { output : { filename : 'my-first-webpack.bundle.js' , }, module : { rules : [{ test : /\.txt$/ , use: 'raw-loader' }], }, }; Copy code

In the above configuration, a single module object is defined

rules
Properties, which contains two required properties:
test
with
use
. This tells the webpack compiler (compiler) the following information:

"Hey, webpack compiler, when you come across "in

require()
/
import
When the statement is parsed as the path of'.txt'", before you package it, use (use)
raw-loader
Convert it. "

Below we will elaborate on commonly used loaders

Plugin

Let's see the official introduction

To use a plugin, you only need

require()
It and then add it to
plugins
Array. Most plug-ins can be customized through options. You can also use the same plug-in multiple times for different purposes in a configuration file. In this case, you need to use
new
Operator to create a plug-in instance.

@1 introduction

@2 New in the plugins array

In this step, let s briefly understand how to use plugin.

Below we will elaborate on commonly used plugins

const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ); //install via npm const webpack = require ( 'webpack' ); //used to access built-in plugins module .exports = { plugins : [ new HtmlWebpackPlugin({ template : './src/index.html' }) ], }; Copy code

1.3 Some basic needs

1.3.1 Introduce html to automatically associate with packaged js

www.npmjs.com/package/htm...

@1 npm i -D html-webpack-plugin

This is a plugin, so follow the plugin usage rules mentioned above

const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) module .exports = { entry : 'index.js' , output : { path : __dirname + '/dist' , filename : 'index_bundle.js' }, plugins : [ new HtmlWebpackPlugin() ] } Copy code

There are some common parameters in an object passed in new HtmlWebpackPlugin()

  • template specifies the html template address string

  • templateContent specifies the template

    templateContent = `<html> ..... </html>` Copy code
  • filename The name of the packaged file

    //[hash] generates a random hash value is valid to clear the cache filename : 'WebPACK [hash] .html' duplicated code
  • title specifies the title of html1 if you follow the syntax of ejs

    • <title><%= htmlWebpackPlugin.options.title %></title>

    We can play like this

    @1 Create a new public folder in the root directory

    @2 Create an index.html as an html template in the public folder

    @3 configuration

    plugins:[ new HtmlWebpackPlugin({ template : './public/index.html' }) ] Copy code

    @4 Packaging

    After that, you can see that an index.html is generated in the dist folder and automatically help us associate the packaged js

1.3.2 Each time you pack and clear the previously packed files

www.npmjs.com/package/cle...

@1 introduction

const {} = CleanWebpackPlugin the require ( 'Clean-WebPACK-plugin' ); duplicated code

@2 Use the plugin

plugins:[ CleanWebpackPlugin(); ] Copy code

In this way, you will find every time

npm run build
Is a new dist

1.3.3 Introduce css

Because webpack only recognizes js and json files, you need to introduce loader to tell webpack to load CSS files

@1 Install related loader

npm install css-loader style-loader duplicated code

@2 Introduce css to js

Import './test.css' duplicated code

@3 Configure loader

module : { rules : [ { test : /\.txt$/ , use: 'raw-loader' }, { test : /\.css$/ , //The principle of parsing from right to left use:[ 'style-loader' , 'css-loader' ] }, ] }, Copy code

Execute css-loader first

  • The role of css-loader is to process external resources in css
  • In layman's terms, it is to turn the css introduced by import/require into a resource recognized by webpack

Then execute style-loader

+ The pattern inserted into the DOM, by inserting a style tags in the head, and the pattern is written into the tag's innerHTML copy the code

There will be styles in the packaged index.html

1.3.4 Improve the compatibility of the introduction of css

www.npmjs.com/package/pos...

Why introduce postcss-loader

Figure

@1 installation

npm install --save-dev postcss-loader postcss duplicated code

@2 How to use

  • Introduced in loader

  • Write a postcss.config.js configuration file in the root directory

    module .exports = { plugins : [ [ "postcss-preset-env" , { //Options }, ], ], }; Copy code
  • Configure.browserslistrc

So what is browserslistrc?

Can refer to this

www.jianshu.com/p/d45a31c50...

cover 99.9% copy code
  • Compatible with 99.9% browsers on the market

This thing is mainly to configure browser compatibility

//.browserslistrc last 1 version > 1 % maintained node versions not dead Copy code

1.3.5 Split CSS

Directly insert the style tag into link introduction

www.npmjs.com/package/min...

@1 installation

npm install --save-dev mini-css -extract-plugin duplicated code

@2 use

const MiniCssExtractPlugin = require ( 'mini-css-extract-plugin' ); module .exports = { plugins : [ new MiniCssExtractPlugin()], module : { rules : [ { test : /\.css$/i , use: [MiniCssExtractPlugin.loader, 'css-loader' ], }, ], }, }; Copy code
  • Where to put the packaged css in dist

1.3.5 Import pictures

Before webpack 5, it was common to use:

Let's use it first

url-loader
file-loader

@1 installation

npm install url-loader file-loader --save-dev copy the code

@2 Introduce image resources

import img from './image.png' ; copy the code

@3 configuration

{ test : /\.(png|jpg|gif)$/i , use: [ { loader : 'url-loader' , options : { limit : 1024 * 50 , name : 'imgs/[name].[ext]' }, }, ], }, Copy code
  • limit limit size 1024 * 50 is 50kb
  • Where to put the name file [name] means the original name [ext] means the suffix of the original file

The official website says that if the size exceeds the limit limit, it will be used

file-loader

In other words, if it is not more than a base64 picture, the picture will not be packaged.

More than an http path address will package the picture

Use base64 to reduce http requests and optimize web pages


effect

The original size of the picture is 51.4KB. I set the limit to 50kb


webpack5

Asset module type, replace all these loaders by adding 4 new module types:

  • asset/resource
    Send a separate file and export the URL. Before by using
    file-loader
    achieve.
  • asset/inline
    Export the data URI of a resource. Before by using
    url-loader
    achieve.
  • asset/source
    Export the source code of the resource. Before by using
    raw-loader
    achieve.
  • asset
    Automatically choose between exporting a data URI and sending a separate file. Before by using
    url-loader
    , And configure the resource volume limit to achieve.

Take an example and package it into base64

{ test : /\.(png|jpg|gif)$/i , type: 'asset/inline' } Copy code

So how do you specify the path and text of the image after asset/resource packaging?

Take a look at the official documentation

by default,

asset/resource
Module with
[hash][ext][query]
The file name is sent to the output directory.

It can be set in the webpack configuration

To modify this template string:

So we need to set in output

output: { path : path.resolve(__dirname, 'dist' ), filename : 'mywebpack.js' , assetModuleFilename : 'images/[name][ext]' }, Copy code

1.4 Split configuration file/split webpack.config.js

Take a look at what the official says

There are huge differences in the build goals between development (development environment) and production (production environment) . In the development environment , we need: a powerful source map and a localhost server with live reloading (real-time reloading) or hot module replacement (hot module replacement) capabilities. The production environment goal is shifted to other areas, focusing on compressing bundles, lighter source maps, resource optimization, etc., and improving load time through these optimization methods. Due to logical separation, we usually recommend writing independent webpack configurations for each environment .

Although more than we produce environment and development environment to do a subtle distinction, but please note that we will follow the principle of non-repetition (Do not repeat yourself - DRY) , to retain a "common (generic)" configuration. In order to merge these configurations together, we will use a file called

Tool of. This tool references the "common" configuration, so we don't have to write duplicate code in environment-specific configurations.

webpack.docschina.org/guides/prod...

@1 installation

npm install --save-dev webpack-merge copy the code

@2 Create a new config directory

Split the original webpack.config.js

+ Common configuration webpack.common.js + Development environment configuration webpack.dev.js + Production environment configuration webpack.production Copy code
- | - webpack.config.js + | - webpack.common.js + | - webpack.dev.js + | - webpack.prod.js copy the code

@3 Write configuration

Common configuration webpack.common.js

const path = require ( "path" ); module .exports = { entry : './src/index.js' , output :{ path : path.resolve(__dirname), filename : 'mywebpack.js' , } } Copy code

Development environment configuration webpack.dev.js

const {merge} = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode:'development' }); Copy code

Production environment configuration webpack.prod.js

const {merge} = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode:'production' }); Copy code

2. Development server (
devServer
)

First of all, we need to know that the bottom layer of webpack-dev-server is the http module of nodejs

Running it will run the packaged index.html

@1 installation

npm i webpack-dev-server copy the code

@2 Use webpack-dev-server

Configure @2.1

var path = require ( 'path' ); module .exports = { //... devServer : { contentBase : path.join(__dirname, 'dist' ), compress : true , port : 9000 , }, }; Copy code

@2.2 Add serve after webpack

When serving (

server
) After startup, output a message before parsing the module list:


Next are some attributes related to webpack server

contentBase

Tell the server the source of the content. Configure only when you need to provide static files

const path = require ( 'path' ); module .exports = { //... devServer : { contentBase : path.join(__dirname, 'public' ), }, }; Copy code

before

Provides an in

devServer
All internal middleware execute the custom execution function before.

Take a look at the official example

module .exports = { //... devServer : { before : function ( app, server, compiler ) { app.get( '/some/path' , function ( req, res ) { res.json({ custom : 'response' }); }); }, }, }; Copy code

Do the friends who know the node express framework think that the interface syntax of express is very similar

Let's request it with get

Can run through

We can use this feature to simulate requests to make some fake data


In the template index.html

fetch( '/api/list' ).then( ( res ) => { return res.json() }).then( ( res ) => { console .log(res); }) Copy code

webpack.config.js

before: function ( app, server, compiler ) { app.get( '/api/list' , function ( req, res ) { res.json({ custom : 'Hello' }); }); }, Copy code

open

Tell dev-server to open the browser after the server starts. Set it to

true
To open the default browser

module.exports = { //... devServer: { open: true, }, }; Copy code

proxy

The Vue.config.js that configures the proxy is similar to this. Its underlying layer may be merged with the webpack configuration.

Simple writing

module .exports = { //... devServer : { proxy : { '/api' : 'http://localhost:3000' , }, }, }; Copy code

Any request starting with/api will be forwarded to http://localhost:3000

Expanded writing

module.exports = { //... devServer: { proxy: { '/api': { target:'http://localhost:3000', pathRewrite: {'^/api':'' }, }, }, }, }; Copy code

Any request starting with/api will be forwarded to http://localhost:3000 and'/api' will be rewritten to an empty string

For example, the actual request is the/list interface

Axios ( '/API/List' ) .then ( RES => {}) copy the code

changeOrigin: true

By default, the source of the host header will be retained when proxying, you can change

changeOrigin
Set as
true
To override this behavior

Sometimes this thing can sometimes trick the back-end interception

For example, the interface for sending requests from localhost:3000 to localhost:9000 is/list

changeOrigin: true -> the origin obtained by the backend (host/origin) localhost:9000

changeOrigin: false -> the origin obtained by the backend (host/origin) localhost:3000

progress

Output the running progress to the console

Instructions

webpack serve --progress copy the code

hotOnly

Enable hot module replacement (see

) Without a page refresh as a fallback when the build fails. Hot update

webpack.config.js

module .exports = { //... devServer : { hotOnly : true , }, }; Copy code

Use via command line

webpack serve --hot-only copy the code