Webpack 5 learning notes

1 Introduction to webpack

1.1 what is a webpack

Webpack is a front-end resource building tool, a static module bundler. In the view of webpack, all resource files (js/json/css/img/less /...) of the front end will be processed as modules. It will perform static analysis according to the dependency of the module and package the corresponding static resources (bundles).

1.2 five core concepts of webpack

1.2.1Entry

The entry indicates which file is the starting point for webpack to start packaging, analyze and build the internal dependency diagram.

1.2.2Output

Output indicates where and how to name the resource bundles packaged by webpack.

1.2.3Loader

Loader enables webpack to handle non JavaScript files (webpack itself only understands JavaScript), which is equivalent to a translator

1.2.4Plugins

Plugins can be used to perform a wider range of tasks. Plug ins range from packaging optimization and compression to redefining variables in the environment

1.2.5Mode

Mode indicates that the webpack uses the configuration of the corresponding mode.

optiondescribecharacteristic
developmentProcess. In DefinePlugin env. NODE_ The value of Env is set to development. Enable NamedChunksPlugin and namedmodules plugin.An environment in which code can be debugged and run locally
productionProcess. In DefinePlugin env. NODE_ The value of Env is set to production. Enable FlagDependencyUsagePlugin, FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin,OccurrenceOrderPlugin, SideEffectsFlagPlugin and TerserPlugin.Environment that allows code optimization to run online

2: The first experience of webpack

2.1 initialization configuration

  1. Initialize package JSON input instruction:
npm  init
  1. Download and install the webpack input command:
npm  install  webpack  webpack-cli -g 
npm  install  webpack  webpack-cli -D

2.2 compiling and packaging applications

1. Create a file
2. Operation instruction

Development environment Directive:

webpack ./src/index.js -o ./build/built.js --mode=development

Function:
webpack will start with/ src/index.js starts packaging for the entry file and outputs it to/ build/built.js overall packaging environment is the development environment; webpack can compile and package js and json files, and convert the modular syntax of es6 into the syntax recognized by the browser.
Production environment Directive:

webpack ./src/index.js -o ./build/built.js --mode=production

Function:
webpack will start with/ src/index.js starts packaging for the entry file and outputs it to/ build/built.js overall packaging environment, which is the production environment; In the development configuration function, there is one more function to compress the code.

3. Conclusion

webpack itself can handle js/json resources, not css/img and other resources
The production environment and development environment compile ES6 modularization into modularization that can be recognized by the browser, but they can not process the basic syntax of ES6 into ES5 (with the help of loader)
The production environment has one more compressed js code than the development environment

3: Basic configuration of webpack development environment

3.1 creating a profile

1. Create the file webpack config. js
2. Configuration contents are as follows:
const { resolve } = require('path');/ /node Built in core module,Used to deal with path problems 
module.exports = {
entry: './src/js/index.js',
/ / Entry file
output: {
/ / Output configuration
filename: './built.js',
/ / Output file name
path: resolve(__dirname, 'build/js')
/ / Output file path configuration
},
mode: 'development'
/ / Development environment
};
3. Operation instruction:
webpack 
4. Conclusion: the function is the same as that in the previous section

3.2 packaging style resources

1. Create a file

2. Download and install the loader package
npm i css-loader style-loader less-loader less -D
3. Modify the configuration file
// resolve the method used to splice absolute paths
const { resolve } = require('path');
module.exports = {
  // webpack configuration / / entry starting point 
  entry: './src/index.js',
  // output 
  output: {
    // Output file name: 'build js',
    // Output path 
    // __ The variable of dirname nodejs represents the absolute directory path of the current file 
    path: resolve(__dirname, 'build')
  },
  // Configuration of loader
  module: {
    rules: [
      // Detailed loader configuration
      // Different files must be configured with different loader processing 
      {
        // Which files match 
        test: /\.css$/,
        // Which loader s are used for processing 
        use: [
          // The order of loader execution in the use array: from right to left, from bottom to top
          // Create a style tag, insert the style resource in js, and add it to the head to take effect
          'style-loader',
          // Change the css file into a commonjs module and load it into js, where the content is a style string 
          'css-loader'
        ]
      }, {
        test: /\.less$/,
        use: ['style-loader', 'css-loader',
          // Compile less files into css files 
          // You need to download less loader and less
          'less-loader'
        ]
      }
    ]
  },
  // plugins configuration 
  plugins: [
    // Detailed plugins configuration
  ],
  // pattern
  mode: 'development',
  // Development mode 
  // mode: 'production'
}
  1. Run command: webpack
webpack

3.3 packaging HTML resources

1. Create a file

2. Download and install the plugin package
npm install --save -dev html-webpack-plugin 
3. Modify the configuration file
const { resolve } = require('path'); 
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // Configuration of loader 
    ]
  }, plugins: [
    // plugins configuration 
    // html-webpack-plugin 
    // Function: an empty HTML will be created by default, and all resources (JS/CSS) for packaged output will be automatically introduced 
    // Requirements: a structured HTML file is required 
    new HtmlWebpackPlugin({
      // Copy '/ src/index.html 'file and automatically import all resources (JS/CSS) for packaged output 
      template: './src/index.html'
    })
  ],
  mode: 'development'
};

4. Operation instruction:

webpack

3.4 packaging picture resources

1. Create a file

2. Download and install the loader package
npm  install --save-dev html-withimg-loader url-loader file-loader
3. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  }, module: {
    rules: [
      {
        test: /\.less$/,
        // To use multiple loader s, use
        use: ['style-loader', 'css-loader', 'less-loader']
      }, {
        // Problem: img images in html cannot be processed by default 
        // Processing picture resources 
        test: /\.(jpg|png|gif)$/,
        // Use a loader 
        // Download URL loader file loader 
        loader: 'url-loader',
        options: {
          // If the image size is less than 8kb, it will be processed by base64 
          // Advantages: reduce the number of requests (reduce server pressure) 
          // Disadvantages: larger picture size (slower file request) 
          limit: 8 * 1024,
          // Problem: by default, the URL loader uses es6 modular parsing, while the image introduced by HTML withimg loader is commonjs 
          // There will be a problem when parsing: [object Module] 
          // Solution: turn off es6 modularization of URL loader and use commonjs for parsing 
          esModule: false,
          // Rename the picture / / [hash:10] take the first 10 bits of the hash of the picture 
          // [ext] get the original file extension 
          name: '[hash:10].[ext]'
        }
      }, {
        // Parsing image resources in html
        test: /\.(html|htm)$/i,
        use: 'html-withimg-loader',
       }
    ]
  }, plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  mode: 'development'
}; 
4. Operation instruction:
webpack

3.5 packaging other resources

1. Create a file

2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      // Package other resources (resources other than html/js/css resources) 
      {
        // Exclude css/js/html resources 
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]'
        }
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  mode: 'development'
}; 
3. Operation instruction:
webpack

Standby: summary of the above resource types 1-5:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.(gif|img|png|jpg)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false
        }
      }, {
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]'
        }
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  mode: 'development'
}

3.6 devserver

Development server devServer: it is used for automation. It does not need to re-enter the webpack and package it every time after modification (automatically compile, automatically open the browser, and automatically refresh the browser)
Features: it can only compile and package in memory without any output (the build package packaged and output will not be seen outside as before, but in memory and will be automatically deleted after closing)
The instructions to start devServer are: NPX webpack dev server or npx webpack serve

1. Create a file

2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
 entry: './src/index.js',
 output: {
   filename: 'built.js',
   path: resolve(__dirname, 'build')
 },
 module: {
   rules: [{
     test: /\.css$/, use: ['style-loader', 'css-loader']
   },
   // Package other resources (resources other than html/js/css resources) 
   {
     // Exclude css/js/html / image resources 
     exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
     loader: 'file-loader',
     options: { name: '[hash:10].[ext]' }
   }
   ]
 },
 plugins: [
   new HtmlWebpackPlugin({ template: './src/index.html' })],
 mode: 'development',
 devServer: {
   // Project post build path 
   contentBase: resolve(__dirname, 'build'),
   // Start gzip compression 
   compress: true,
   // Port number 
   port: 3000,
   // Open browser automatically 
   open: true
 }
};
3. Operation instruction:
npx webpack-dev-server or npx webpack serve

3.7 development environment configuration

1. Create a file

2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { 
entry: './src/js/index.js', 
output: { 
filename: 'js/built.js', 
path: resolve(__dirname, 'build') }, 
module: { 
rules: [ 
// Configuration of loader 
{ 
// Handling less resources
 test: /\.less$/,
  use: ['style-loader', 'css-loader', 'less-loader'] 
  },{ 
   // Handling css resources 
   test: /\.css$/, 
   use: ['style-loader', 'css-loader'] 
   }, { 
   // Processing picture resources 
   test: /\.(jpg|png|gif)$/, 
   loader: 'url-loader', 
   options: { 
   limit: 8 * 1024, 
   name: '[hash:10].[ext]',
    // Turn off es6 modularization 
    esModule: false, 
    outputPath: 'imgs' 
    }
     }, { 
     // Processing img resources in html 
     test: /\.html$/, 
     loader: 'html-loader' }, { 
// Processing other resources 
exclude: /\.(html|js|css|less|jpg|png|gif)/,
 loader: 'file-loader', 
 options: {
     name: '[hash:10].[ext]', outputPath: 'media'
}
}
]
}, plugins: [
 // plugins configuration 
 new HtmlWebpackPlugin({ template: './src/index.html' })
  ],
  mode: 'development', 
  devServer: { 
  contentBase: resolve(__dirname, 'build'), 
  compress: true,
   port: 3000, 
   open: true 
   } 
   };
9. Operation instruction:
npx webpack-dev-server 

4. Basic configuration of webpack production environment

4.1 extract css into a separate file

4.1. 1. Download the installation package

4.1. 2. Download plug-ins

npm install--save-dev mini-css-extract-plugin 
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // Create a style label and put the style into
          // 'style-loader', 
          // This loader replaces style loader. Function: extract css in js into a separate file 
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader, 
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.(gif|img|png|jpg)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false,
          outputPath: 'images'
        }
      },
      {
        // Processing img resources in html
        test: /\.(html|htm)$/i,
        use: 'html-withimg-loader', // Parsing image resources in html
      },
      {
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'assets'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin({ filename: 'css/built.css' })],
  mode: 'development',
  devServer: {
    // Project post build path 
    contentBase: resolve(__dirname, 'build'),
    // Start gzip compression 
    compress: true,
    // Port number 
    port: 3000,
    // Open browser automatically 
    open: true
  }
}

4.1. 3. Operation instruction:

npx webpack  serve 

Note: we include pictures in the packaged resources, so we need to configure the public path in output. publicPath: '/ build /'

4.2css compatibility processing

4.2. 1. Download loader

npm install--save -dev postcss-loader postcss-preset-env 

4.2. 2. Modify the configuration file

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// Set nodejs environment variable
process.env.NODE_ENV = 'development';
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: { 
              postcssOptions: { 
                ident: "postcss", 
                plugins: [require("postcss-preset-env")()] } 
              }
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.(gif|img|png|jpg)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false,
          outputPath: 'images'
        }
      },
      {
        // Processing img resources in html
        test: /\.(html|htm)$/i,
        use: 'html-withimg-loader', // Parsing image resources in html
      },
      {
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'assets'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin({ filename: 'css/built.css' }),
  ],


  mode: 'development',
  devServer: {
    // Project post build path 
    contentBase: resolve(__dirname, 'build'),
    // Start gzip compression 
    compress: true,
    // Port number 
    port: 3000,
    // Open browser automatically 
    open: true
  }
}

4.2. 3. Modify package json

"browserslist": {
   "development": [
     "last 1 chrome version",
     "last 1 firefox version",
     "last 1 safari version"
   ],
   "production": [
     ">0.1%",
     "not dead",
     "not op_mini all"
   ]
 }

4.2. 4. Operation instruction:

webpack

4.2. 5. Implementation effect:

Development environment:

Production environment:

4.3 compressing css

1. Download the installation package
npm install--save -dev optimize-css-assets-webpack-plugin 
2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// Set nodejs environment variable. The default is production environment
process.env.NODE_ENV = 'development';
module.exports = {
 entry: './src/js/index.js',
 output: {
   filename: 'js/built.js',
   path: resolve(__dirname, 'build'),
   publicPath: '/build/'
 },
 module: {
   rules: [
     {
       test: /\.css$/,
       use: [
         // 'style-loader',
         MiniCssExtractPlugin.loader,
         'css-loader',
         {
           loader: 'postcss-loader',
           options: { postcssOptions: { ident: "postcss", plugins: [require("postcss-preset-env")()] } }
         }
       ]
     },
     {
       test: /\.less$/,
       use: [
          //'style-loader',
          MiniCssExtractPlugin.loader,
         'css-loader',
          {
           loader: 'postcss-loader',
           options: { 
             postcssOptions: { 
               ident: "postcss", 
               plugins: [require("postcss-preset-env")()] } 
             }
         },
         'less-loader'
       ]
     },
     {
       test: /\.(gif|img|png|jpg)$/,
       loader: 'url-loader',
       options: {
         limit: 8 * 1024,
         name: '[hash:10].[ext]',
         esModule: false,
         outputPath: 'images'
       }
     },
     {
       // Processing img resources in html
       test: /\.(html|htm)$/i,
       use: 'html-withimg-loader', // Parsing image resources in html
     },
     {
       exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
       loader: 'file-loader',
       options: {
         name: '[hash:10].[ext]',
         outputPath: 'assets'
       }
     }
   ]
 },
 plugins: [
   new HtmlWebpackPlugin({ template: './src/index.html' }),
   new MiniCssExtractPlugin({ filename: 'css/built.css' }),
   // Compress css
   new OptimizeCssAssetsWebpackPlugin()
 ],


 mode: 'development',
 devServer: {
   // Project post build path 
   contentBase: resolve(__dirname, 'build'),
   // Start gzip compression 
   compress: true,
   // Port number 
   port: 3000,
   // Open browser automatically 
   open: true
 }
}
3. Operation instruction:
webpack
4. Effect:

4.4 JS syntax check

1. Download the installation package
 npm install--save -dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// Set nodejs environment variable. The default is production environment
// process.env.NODE_ENV = 'development';
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: { postcssOptions: { ident: 'postcss', plugins: [require('postcss-preset-env')()] } },
          },
        ],
      },
      {
        test: /\.less$/,
        use: [
           //'style-loader',
           MiniCssExtractPlugin.loader,
           'css-loader',
           {
            loader: 'postcss-loader',
            options: { 
              postcssOptions: { 
                ident: "postcss", 
                plugins: [require("postcss-preset-env")()] } 
              }
          },
           'less-loader',
        ],
      },
      {
        test: /\.(gif|img|png|jpg)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false,
          outputPath: 'images',
        },
      },
      {
        // Processing img resources in html
        test: /\.(html|htm)$/i,
        use: 'html-withimg-loader', // Parsing image resources in html
      },
      {
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'assets',
        },
      },
      /*
          Syntax check: eslint loader
          Note: only check the source code written by yourself, and third-party libraries do not need to be checked
          Set check rule: package Set in eslintConfig in JSON~
          "eslintConfig": {
            "extends": "airbnb-base"
          }
          airbnb Required syntax dependency -- > eslint config airbnb base eslint plugin import eslint
      */
      {
        test: /\.js$/,
        // Path that does not require syntax checking
        exclude: /node_modules/,
        // Specify the directory to check
        include: [path.resolve(__dirname, 'src')],
        loader: 'eslint-loader',
        // Pre compile check
        enforce: 'pre'
        options: {
           // Automatic repair
          fix: true,
        },,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin({ filename: 'css/built.css' }),
    // Compress css
    new OptimizeCssAssetsWebpackPlugin(),
  ],

  mode: 'development',
  devServer: {
    // Project post build path
    contentBase: resolve(__dirname, 'build'),
    // Start gzip compression
    compress: true,
    // Port number
    port: 3000,
    // Open browser automatically
    open: true,
  },
};
3. Configure package json
"eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  }
4. Operation instruction:
webpack

remarks:

  • 1. When debugging, we cannot avoid some eslint warnings. We can use / / eslint disable next line to make the next line not subject to eslint check, such as:

  • 2. Detailed configuration of eslint: https://www.cnblogs.com/jackson1/p/12682664.html

4.5 js compatibility processing

1. Download the installation package
npm install --save -dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js
2. Modify the configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// Set nodejs environment variable. The default is production environment
// process.env.NODE_ENV = 'development';
module.exports = {
 entry: './src/js/index.js',
 output: {
   filename: 'js/built.js',
   path: resolve(__dirname, 'build'),
   publicPath: '/build/',
 },
 module: {
   rules: [
     {
       test: /\.css$/,
       use: [
         // 'style-loader',
         MiniCssExtractPlugin.loader,
         'css-loader',
         {
           loader: 'postcss-loader',
           options: { postcssOptions: { ident: 'postcss', plugins: [require('postcss-preset-env')()] } },
         },
       ],
     },
     {
       test: /\.less$/,
       use: [
         // 'style-loader',
         MiniCssExtractPlugin.loader,
         'css-loader',
         {
           loader: 'postcss-loader',
           options: { 
             postcssOptions: { 
               ident: "postcss", 
               plugins: [require("postcss-preset-env")()] } 
             }
         },
         'less-loader',
       ],
     },
     {
       test: /\.(gif|img|png|jpg)$/,
       loader: 'url-loader',
       options: {
         limit: 8 * 1024,
         name: '[hash:10].[ext]',
         esModule: false,
         outputPath: 'images',
       },
     },
     {
       // Processing img resources in html
       test: /\.(html|htm)$/i,
       use: 'html-withimg-loader', // Parsing image resources in html
     },
     {
       exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
       loader: 'file-loader',
       options: {
         name: '[hash:10].[ext]',
         outputPath: 'assets',
       },
     },
     /*
         Syntax check: eslint loader
         Note: only check the source code written by yourself, and third-party libraries do not need to be checked
         Set check rule: package Set in eslintConfig in JSON~
         "eslintConfig": {
           "extends": "airbnb-base"
         }
         airbnb Required syntax dependency -- > eslint config airbnb base eslint plugin import eslint
     */
     {
       test: /\.js$/,
       // Path that does not require syntax checking
       exclude: /node_modules/,
       // Specify the directory to check
       include: [resolve(__dirname, 'src')],
       loader: 'eslint-loader',
       // Check before compiling
       enforce: 'pre',
       options: {
         // Automatic repair
         fix: true,
       },
     },
     /*
      js Compatibility processing: you need to download Babel loader @ Babel / core
        1. Basic js compatibility processing -- > @ Babel / preset env
          Problem: only basic syntax can be converted, such as promise advanced syntax
        2. All js compatibility processing -- > @ Babel / Polyfill
          Problem: as long as some compatibility problems are solved, but all compatibility codes are introduced, the volume is too large
        3. If compatibility processing is required, do it: load -- > core JS on demand
      Final scheme: @ Babel / preset env + core JS
    */
     {
       test: /\.js$/,
       exclude: /node_module/,
       loader: 'babel-loader',
       options: {
         presets: [
           [
             // Basic preset
             '@babel/preset-env',
             {
               // Load on demand
               useBuiltIns: 'usage',
               // Specify the core JS version
               corejs: { version: 3 },
               // Specifies which version of browser is compatible with
               targets: {
                 chrome: '60',
                 firefox: '50',
                 ie: '9',
                 safari: '10',
                 edge: '17',
               },
             },
           ],
         ],
       },
     },
   ],
 },
 plugins: [
   new HtmlWebpackPlugin({ template: './src/index.html' }),
   new MiniCssExtractPlugin({ filename: 'css/built.css' }),
   // Compress css
   new OptimizeCssAssetsWebpackPlugin(),
 ],

 mode: 'development',
 devServer: {
   // Project post build path
   contentBase: resolve(__dirname, 'build'),
   // Start gzip compression
   compress: true,
   // Port number
   port: 3000,
   // Open browser automatically
   open: true,
 },
};
3. Implementation
webpack
4. Implementation effect

4.6 js compression and HTML compression

4.6.1 js compression

js code will be automatically compressed in the production environment; In webopack config. js file directly modify the mode

 mode: 'production' 

4.6.2 HTML compression

When using HtmlWebpackPlugin, we can add the minify configuration item

  new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        // Remove spaces:
        collapseWhitespace: true,
        // Remove comment
        removeComments: true
      }
    }),

4.7 summary: webpack production environment configuration summary:

1. Document directory

2.webpack configuration file
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// Separate files for css production
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// Compress css
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// Set nodejs environment variable. The default is production environment
process.env.NODE_ENV = 'development';
// loader configuration of reusable css
const commCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      postcssOptions: {
        ident: 'postcss',
        plugins: [require('postcss-preset-env')()]
      }
    },
  }]
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          ...commCssLoader
        ],
      },
      {
        test: /\.less$/,
        use: [
          ...commCssLoader,
          'less-loader',
        ],
      },
      {
        test: /\.(gif|img|png|jpg)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false,
          outputPath: 'images',
        },
      },
      {
        // Processing img resources in html
        test: /\.(html|htm)$/i,
        use: 'html-withimg-loader', // Parsing image resources in html
      },
      {
        exclude: /\.(css|js|html|less|gif|img|png|jpg)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'assets',
        },
      },
      /*
          Syntax check: eslint loader
          Note: only check the source code written by yourself, and third-party libraries do not need to be checked
          Set check rule: package Set in eslintConfig in JSON~
          "eslintConfig": {
            "extends": "airbnb-base"
          }
          airbnb Required syntax dependency -- > eslint config airbnb base eslint plugin import eslint
      */
      {
        test: /\.js$/,
        // Path that does not require syntax checking
        exclude: /node_modules/,
        // Specify the directory to check
        include: [resolve(__dirname, 'src')],
        loader: 'eslint-loader',
        // Priority execution (check first and then perform compatibility processing)
        enforce: 'pre',
        options: {
          // Automatic repair
          fix: true,
        },
      },
      /*
       js Compatibility processing: you need to download Babel loader @ Babel / core
         1. Basic js compatibility processing -- > @ Babel / preset env
           Problem: only basic syntax can be converted, such as promise advanced syntax
         2. All js compatibility processing -- > @ Babel / Polyfill
           Problem: as long as some compatibility problems are solved, but all compatibility codes are introduced, the volume is too large
         3. If compatibility processing is required, do it: load -- > core JS on demand
       Final scheme: @ Babel / preset env + core JS
     */
      {
        test: /\.js$/,
        exclude: /node_module/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              // Basic preset
              '@babel/preset-env',
              {
                // Load on demand
                useBuiltIns: 'usage',
                // Specify the core JS version
                corejs: { version: 3 },
                // Specifies which version of browser is compatible with
                targets: {
                  chrome: '60',
                  firefox: '50',
                  ie: '9',
                  safari: '10',
                  edge: '17',
                },
              },
            ],
          ],
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        // Remove spaces:
        collapseWhitespace: true,
        // Remove comment
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({ filename: 'css/built.css' }),
    // Compress css
    new OptimizeCssAssetsWebpackPlugin(),
  ],
  // js files are compressed in the production environment
  mode: 'production',
  devServer: {
    // Project post build path
    contentBase: resolve(__dirname, 'build'),
    // Start gzip compression
    compress: true,
    // Port number
    port: 3000,
    // Open browser automatically
    open: true,
  },
};
3.package.json
"browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.1%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  }

5. Optimized configuration of webpack

The optimization is divided into the following aspects:
  • webpack Performance Optimization: development environment and production environment performance optimization;
  • Development environment performance optimization: optimize the speed of packaging and construction, and optimize code debugging
  • Production environment performance optimization: optimize the speed of packaging and construction, and optimize the code running performance

5.1 development environment performance optimization

5.1.1 HMR :

Enable hot module replacement, also known as HMR.
Function: when a module changes, it will only repackage this module (instead of packaging all modules), greatly improving the construction speed
Code: just set hot to true in devServer, and the HMR function will be automatically enabled (only available in development mode)

devServer: {
  contentBase: resolve(__dirname, 'build'),
  compress: true,
  port: 3000,
  open: true,
  // Turn on HMR function
  // When the webpack configuration is modified, the webpack service must be restarted in order for the new configuration to take effect
  hot: true
}

Hot module replacement for each file:
Style file: the HMR function can be used because the style loader used in the development environment implements the hot module replacement function by default
js file: the HMR function cannot be used by default (when a js module is modified, all js modules will be refreshed)
– > to implement HMR, you need to modify js code (add code supporting HMR function)
In index JS file:

// binding
if (module.hot) {
  // Once module If hot is true, HMR function is enabled. -- > Validate HMR function code
  module.hot.accept('./print.js', function() {
    // Method listens for print Once the JS file changes, only this module will be repackaged and built, and other modules will not.
    // The following callback function will be executed
    print();
  });
}

Note: the HMR function can only handle other files that are not imported js files.
html file: the HMR function cannot be used by default (html does not need to be used as the HMR function, because there is only one html file and no further optimization is required)
Using HMR can cause problems: html files cannot be hot updated (they will not be automatically packaged and built)
Solution: modify the entry entry and import the html file (in this way, the html will be refreshed as a whole)
entry: ['./src/js/index.js', './src/index.html']

5.1.2 source-map

source-map:
A technique that provides mapping from source code to post build code (if post build code fails, source code errors can be tracked through mapping)
Parameters:
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

code:

devtool: 'eval-source-map'

Optional scheme: [location where source map is generated | error code information given]
1 . Source map: external error code, accurate information and error location of source code

2. Inline source map: inline. Only one inline source map is generated. The exact information of the error code and the error location of the source code

3. Hidden source map: external, error code, error reason, but there is no error location (to hide the source code). Source code errors cannot be tracked, but only the error location of the built code can be prompted

4. Eval source map: inline. Each file generates a corresponding source map, which is in eval. The exact information of the error code and the error bit of the source code

5. Nosources source map: external, error code, accurate information, but no source code information (to hide the source code)

6. Soap source map: external error code, accurate information and error location of source code. The error can only be accurate to the whole line, and the column is ignored

7. Soap module source map: external error code, accurate information and error location of source code. Module will be added to loader's source map

Difference between inline and external:

  1. File generated externally, not inline
  2. Inline builds are faster

Options for development / production environment:

Development environment:
It needs to be considered that the speed is fast and the debugging is more friendly:
  Fast speed( eval > inline > cheap >... )
 eval-cheap-souce-map
 eval-source-map
*More friendly debugging:
 souce-map
 cheap-module-souce-map
 cheap-souce-map

Finally, the best two schemes are obtained:
1. Eval source map (high integrity, fast inline speed, scaffold is used by default)/
2. Eval soap module soap map (error prompt: ignore column but contain other information, fast inline)

Production environment:
We need to consider whether the source code should be hidden and whether debugging should be more friendly
 Inlining increases the size of the code, so you don't need to inline in the production environment
 Hide source code
nosources-source-map hide all
hidden-source-map If only the source code is hidden, the post build code error message will be prompted

Finally, the best two schemes are obtained:
1. Source map (most complete)
2. Soap module soap map (error prompt: ignore a whole row of columns)

5.2 production environment performance optimization

5.2. 1. Optimize the packaging construction speed

5.2.1.1 oneOf

oneOf: after matching to the loader, it will not be matched backward to optimize the packaging and construction speed of the production environment
code:

module: {
  rules: [
    {
      // js syntax check
      test: /\.js$/,
      exclude: /node_modules/,
      // Priority implementation
      enforce: 'pre',
      loader: 'eslint-loader',
      options: {
        fix: true
      }
    },
    {
      // oneOf optimizes the packaging and construction speed of production environment
      // Only one of the following loader s will be matched (there will be no further matching after matching)
      // Note: two configurations cannot handle files of the same type (so extract the eslint loader and put it outside)
      oneOf: [
        {
          test: /\.css$/,
          use: [...commonCssLoader]
        },
        {
          test: /\.less$/,
          use: [...commonCssLoader, 'less-loader']
        },
        {
          // js compatibility processing
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: {version: 3},
                  targets: {
                    chrome: '60',
                    firefox: '50'
                  }
                }
              ]
            ]
          }
        },
        {
          test: /\.(jpg|png|gif)/,
          loader: 'url-loader',
          options: {
            limit: 8 * 1024,
            name: '[hash:10].[ext]',
            outputPath: 'imgs',
            esModule: false
          }
        },
        {
          test: /\.html$/,
          loader: 'html-loader'
        },
        {
          exclude: /\.(js|css|less|html|jpg|png|gif)/,
          loader: 'file-loader',
          options: {
            outputPath: 'media'
          }
        }
      ]
    }
  ]
},

5.2.1.2 babel cache

babel caching: similar to HMR, it caches the resources processed by babel (update where js changes, and use the previously cached resources for other js), so as to make the second packaging and construction faster
code:

{
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'usage',
          corejs: { version: 3 },
          targets: {
            chrome: '60',
            firefox: '50'
          }
        }
      ]
    ],
    // Enable babel cache
    // On the second build, the previous cache is read
    cacheDirectory: true
  }
},

5.2. 1.3 file resource cache

If the file name remains unchanged, the previously cached resources will not be re requested, but will be used again
1.hash: a unique hash value will be generated each time wepack is packaged.

output: {
    // Adding a hash value to the file name prevents caching
    filename: 'js/built.[hash:10].js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/',
  },
new MiniCssExtractPlugin({ filename: 'css/built.[hash:10].css' }),

Problem: when repackaging, the hsah value of all files will change, which will invalidate all caches. (only one file may have been changed)
2. Chunk hash: hash value generated according to chunk. The hash value from the same chunk is the same
Problem: js and css come from the same chunk, and the hash value is the same (because css loader will load css files into js, they belong to the same chunk)

output: {
    // Adding a hash value to the file name prevents caching
    filename: 'js/built.[chunkhash:10].js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/',
  },
new MiniCssExtractPlugin({ filename: 'css/built.[chunkhash:10].css' }),

3.contenthash: generates a hash value according to the contents of the file. The hash value of different files must be different (the hash in the file name will change only when the file content is modified)
Modify the content of the css file, the hash value of the packaged css file name will change, while the hash value of the js file will not change. In this way, the css and js caches will judge whether to re request resources -- > so that the code can run online and the cache can be used better

output: {
    // Adding a hash value to the file name prevents caching
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build'),
    publicPath: '/build/',
  },
new MiniCssExtractPlugin({ filename: 'css/built.[contenthash:10].css' }),

Packaged file name:

Modify index JS code is repackaged without modifying css code

5.2.1.4 tree shaking

Premise:

  1. ES6 modularization must be used
  2. When the production environment is enabled, the tree shake will be used automatically (in this way, the useless code will be removed automatically)
    Function: remove useless code and reduce code volume
    In package JSON configuration:
"sideEffects": false

Indicates that all codes have no side effects (tree shaking can be performed)
This may cause problems: css / @babel/polyfill files may be killed (side effects); these files are only imported and not used, so they will not be packaged because of tree shaking
Therefore, you can configure:

"sideEffects": ["*.css", "*.less"] 

The css/less file tree shaking is not processed

5.2.1.5 code split

Code segmentation. A large bundle that will be packaged for output JS file is split into multiple small files, so multiple files can be loaded in parallel, which is faster than loading one file.
1. Multi entry splitting (this method can be used for multi page applications)

entry: {
    // Multiple entries: with one entry, the final output will have a bundle
    index: './src/js/index.js',
    test: './src/js/test.js'
  },
  output: {
    // [name]: get file name
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },

Output file after packaging

2.optimization:

optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },

Add node_ The code in modules is packaged separately (more than 30kb in size)
Automatically analyze whether there are public files in the multi entry chunk. If there is, it will be packaged into a single chunk (for example, jquery is introduced into both modules, and it will be packaged into a separate file) (the size is more than 30kb),
example
If we were in index Package after introducing jquery third-party tools into JS:
Packaging without optimization configuration:

Package with optimization configuration:

86kb is the jquery code we introduced; Even if multiple entry files refer to jquery,jquery will only be packaged once
3.import dynamic import syntax: a file is packaged into a chunk through js code

/*
  import Dynamic import syntax: a file can be packaged separately (test file will not be packaged in the same file as index, but separately)
  webpackChunkName:Specify the name of the file after test is packaged separately
*/
import(/* webpackChunkName: 'test' */'./test')
  .then(({ mul, count }) => {
    // File loaded successfully~
    // eslint-disable-next-line
    console.log(mul(2, 5));
  })
  .catch(() => {
    // eslint-disable-next-line
    console.log('File loading failed~');
  });

4. Summary: the common scheme is single entry file + optimization

5.2.1.6 lazy loading

1. Lazy loading: the file is loaded only when it needs to be used (code segmentation is required). However, if the resources are large, the loading time will be long and there will be a delay.
2. Normal loading: it can be considered that parallel loading (loading multiple files at the same time) has no sequence, and loading unnecessary resources first will waste time.
3. Preload prefetch (poor compatibility): it will be loaded in advance before use. After other resources are loaded and the browser is idle, load this resource secretly. In this way, it has been loaded when in use, and the speed is very fast. Therefore, it is better to add preload on the basis of lazy loading.

code:
index.js file

document.getElementById('btn').onclick = function() {
  // Put the contents of import into the asynchronous callback function, click the button, test JS will be loaded (it will not be loaded repeatedly)
  // webpackPrefetch: true indicates that preload is enabled
  import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
    console.log(mul(4, 5));
  });
  import('./test').then(({ mul }) => {
    console.log(mul(2, 5))
  })
};

Analysis: click the btn button and go back to load test JS file and then call the mul() function. When the second click, it will directly get from the cache and call the mul() function
be careful:
The webpack will report an error 'import' and 'export' may only appear at the top level

Solution:
1. Install Babel eslint

npm install --save-dev babel-eslint

2. New eslintrc file

{
  "parser": "babel-eslint",
  "parserOptions": {
      "sourceType": "module",
      "allowImportExportEverywhere": true
  }
}

5.2.1.7 pwa (offline accessible technology)

pwa: offline accessible technology (progressive network development application), using serviceworker and workbox technology. The advantage is that it can be accessed offline, but the disadvantage is poor compatibility.
webpack.config.js configuration:
1. Installation: workbox webpack plugin:

npm install workbox-webpack-plugin --save-dev

2. Use

const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); // Introducing plug-ins

// Add to plugins:
new WorkboxWebpackPlugin.GenerateSW({
  /*
    1. Help service worker start quickly
    2. Delete old serviceworker

    Generate a serviceworker configuration file
  */
  clientsClaim: true,
  skipWaiting: true
})

3. Modify package eslintConfig configuration in JSON (eslint does not know window and navigator global variables)

"eslintConfig": {
    ......
    "env": {
      "browser": true
    }
  }

4.1. serviceWorker code must be running on the server

 npm i serve -g

4.2 start the server and expose all the resources under the build directory of the package output as static resources

serve -s build 

5. Register serviceworker: index JS also needs to write a piece of code to activate its use

if ('serviceWorker' in navigator) { // Handling compatibility issues
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js') // Register serviceWorker
      .then(() => {
        console.log('sw Registration succeeded~');
      })
      .catch(() => {
        console.log('sw Registration failed~');
      });
  });
}

5.2. 1.8 multi process packaging

Multi process Packaging: a task takes a long time and gets stuck. Multiple processes can do multiple things at the same time, which is more efficient.
Advantages: it improves the packing speed,
Disadvantages: the startup and communication of each process will have overhead (Babel loader takes the longest time, so thread loader is used to optimize it)
When there are a lot of js code, the effect of using multi process packaging will be obvious

{
  test: /\.js$/,
  exclude: /node_modules/,
  use: [
    /* 
      thread-loader Multi process packaging will be enabled for the loader behind it (Babel loader in this case). 
      The process startup is about 600ms, and the process communication also has overhead. (the startup cost is expensive, so don't abuse it)
      Only when the work takes a long time, multi process packaging is required
    */
    {
      loader: 'thread-loader',
      options: {
        workers: 2 // 2 processes
      }
    },
    {
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env',
            {
              useBuiltIns: 'usage',
              corejs: { version: 3 },
              targets: {
                chrome: '60',
                firefox: '50'
              }
            }
          ]
        ],
        // Enable babel cache
        // On the second build, the previous cache is read
        cacheDirectory: true
      }
    }
  ]
},

Using multithreaded packaging in a simple project:

Do not use multithreaded packaging:

5.2.1.9 externals

externals: Let some libraries not be packaged through cdn introduce
webpack.config.js Configuration in:
externals: {
  // Refuse jQuery to be packaged (it will be faster if it is introduced through cdn)
  // Ignored library name -- npm package name
  jquery: 'jQuery'
}

Need to be in index Html is introduced through cdn:

<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

5.2.1.10 dll

dll: package some libraries separately, and then directly import them into build. Node can be split in code split_ After modules, dll is used for finer segmentation to optimize the performance of code operation.
1. Add webpack dll. JS file and configure: (package jquery separately)

/*
  node_modules The libraries will be packaged together, but in many cases, the output js file is too large
  Using dll technology, some libraries (third-party libraries: jquery, react, vue...) are packaged separately
  When running webpack, the default is to find webpack config. JS configuration file
  Requirement: you need to run webpack dll. JS file
    --> webpack --config webpack.dll.js(Running this command means packaging with this configuration file)
*/
const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // [name] -- > jQuery generated by final packaging
    // ['jquery] -- > the library to be packaged is jQuery
    jquery: ['jquery']
  },
  output: {
    // Export designation
    filename: '[name].js', // name is jquery
    path: resolve(__dirname, 'dll'), // Package to dll directory
    library: '[name]_[hash]', // What is the name of the content exposed in the packaged library
  },
  plugins: [
    // Package to generate a manifest JSON -- > provides the mapping relationship of jquery (tell webpack: jquery does not need to package and expose the name of the content)
    new webpack.DllPlugin({
      name: '[name]_[hash]', // The exposed content name of the mapping library
      path: resolve(__dirname, 'dll/manifest.json') // Output file path
    })
  ],
  mode: 'production'
};

2. Running this command means packaging with this configuration file (that is, packaging the dependencies in node_module separately)

webpack --config webpack.dll.js

3.webpack.config.js configuration: (tell webpack that jquery does not need to be packaged, and output the previously packaged jquery to the build directory together with other packaged resources)

// Introducing plug-ins
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// Configuration in plugins:
plugins: [
  new HtmlWebpackPlugin({
    template: './src/index.html'
  }),
  // Tell webpack which libraries do not participate in packaging, and the name of the libraries used will change
  new webpack.DllReferencePlugin({
    manifest: resolve(__dirname, 'dll/manifest.json')
  }),
  // Package and output a file to the build directory, and automatically import the resource into html
  new AddAssetHtmlWebpackPlugin({
    filepath: resolve(__dirname, 'dll/jquery.js')
  })
],

4. Packing

webpack

5. Summary:
1. Configure webpack dll. JS file tells webpack that those dependent packages need to be packaged separately
2. Execute: webpack -- config webpack dll. JS, packaged separately, and the separately packaged resource path is recorded in manifest JSON resource mapping file

3. Execute webpack to start project packaging. During the packaging process, manifest JSON gets the separately packaged resource path and introduces it into index HTML file

6.webpack configuration details

entry: Entrance starting point
string --> './src/index.js',Single entry
 Package to form a chunk.  Output a bundle File. here chunk The default name is main
array --> ['./src/index.js', './src/add.js'],Multiple entry
 All entry files will eventually form only one chunk,There is only one output bundle File.
(Generally only used in HMR Let in function html Hot update effective)
object,Multiple entry
 Several entry files form several chunk,Output several bundle File, at this time chunk Your name is key value
--> Special usage:
entry: {
  // In the end, only one chunk will be formed, and only one bundle file will be output.
  index: ['./src/index.js', './src/count.js'], 
  // Form a chunk and output a bundle file.
  add: './src/add.js'
}

6.2 output

output: {
  // File name (specify name + directory)
  filename: 'js/[name].js',
  // Output file directory (public directory for future output of all resources)
  path: resolve(__dirname, 'build'),
  // All resources introduce a common path prefix -- > 'IMGs / a.jpg' -- > '/ IMGs / a.jpg'
  publicPath: '/',
  chunkFilename: 'js/[name]_chunk.js', // Specifies the name of the non entry chunk
  library: '[name]', // Variable names exposed after packaging the entire library
  libraryTarget: 'window' // To which browser: window is the variable name added
  // libraryTarget: 'global' // node: global
  // libraryTarget: 'commonjs' // conmmonjs module exports
},

6.3 module

module: {
  rules: [
    // Configuration of loader
    {
      test: /\.css$/,
      // Multiple loader s use
      use: ['style-loader', 'css-loader']
    },
    {
      test: /\.js$/,
      // Exclude node_ js file under modules
      exclude: /node_modules/,
      // Only check js files under src
      include: resolve(__dirname, 'src'),
      enforce: 'pre', // Priority implementation
      // enforce: 'post', / / postpone execution
      // Single loader
      loader: 'eslint-loader',
      options: {} // Specify configuration options
    },
    {
      // Only one of the following configurations will take effect
      oneOf: []
    }
  ]
},

6.4 resolve

// Rules for parsing modules
resolve: {
  // Configure the path alias of the resolution module: advantages: when the directory level is very complex, it shortens the path; Disadvantages: the path does not prompt
  alias: {
    $css: resolve(__dirname, 'src/css')
  },
  // Omit the suffix of the configuration file path (you can not write the file suffix when importing)
  extensions: ['.js', '.json', '.jsx', '.css'],
  // Tell the webpack parsing module which directory to look for
  modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}

After this configuration, the import file can be abbreviated as follows: import '$css/index';

6.5 dev server

devServer: {
  // The directory where the code is running
  contentBase: resolve(__dirname, 'build'),
  // Monitor all files in the contentBase directory, and reload if the file changes
  watchContentBase: true,
  watchOptions: {
    // Ignore file
    ignored: /node_modules/
  },
  // Start gzip compression
  compress: true,
  // Port number
  port: 5000,
  // domain name
  host: 'localhost',
  // Open browser automatically
  open: true,
  // Turn on HMR function
  hot: true,
  // Do not display startup server log information
  clientLogLevel: 'none',
  // Do not display anything except some basic information
  quiet: true,
  // If something goes wrong, don't give a full screen prompt
  overlay: false,
  // Server agent, -- > solve the cross domain problem of development environment
  proxy: {
    // Once the devServer(5000) server receives the request for / api/xxx, it forwards the request to another server 3000
    '/api': {
      target: 'http://localhost:3000',
      // When sending a request, the request path is rewritten: change / api / xxx -- > / xxx (remove / api)
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

Among them, cross domain problem: different protocols, port numbers and domain names in the same source strategy will produce cross domain problems.
There is cross domain between normal browsers and servers, but there is no cross domain between servers. The code runs through the proxy server, so there is no cross domain between the browser and the proxy server. The browser sends the request to the proxy server, and the proxy server forwards it to another server for you. There is no cross domain between the servers, so the request is successful. The proxy server then sends the received response to the browser. This solves the cross domain problem in the development environment.

6.6 optimization

Content hash caching can cause a problem: modifying a file causes the content hash of b file to change.
Because in index a.js is introduced into JS, and index.js is packaged JS records the hash value of a.js. When a.js changes, the repackaged hash changes, resulting in index The hash of a.js recorded in the content of JS file is also changed, so index. JS is repackaged The hash value of JS will also change, which will invalidate the cache. (the a.js file is changed, but the hash value of the index.js file is also changed)
Solution: runtimechunk -- > package the hashes of other modules recorded by the current module into a separate runtime file. In this way, the hash change of a.js will only affect the runtime file, not the index JS file

output: {
  filename: 'js/[name].[contenthash:10].js',
  path: resolve(__dirname, 'build'),
  chunkFilename: 'js/[name].[contenthash:10]_chunk.js' // Specify the names of other chunks that are not entry files_ chunk
},
optimization: {
  splitChunks: {
    chunks: 'all',
    /* The following are the default configurations of splitChunks, which can be left blank
    miniSize: 30 * 1024, // The minimum chunk for segmentation is 30kb (only those larger than 30kb can be segmented)
    maxSize: 0, // There is no limit to the maximum
    minChunks: 1, // The chunk to be extracted is referenced at least once
    maxAsyncRequests: 5, // The maximum number of files loaded in parallel when loading on demand is 5
    maxInitialRequests: 3, // Maximum number of parallel requests for entry js file
    automaticNameDelimiter: '~', // Name connector
    name: true, // You can use naming rules
    cacheGroups: { // Split chunk s
      vendors: {
        // node_modules The files in will be packaged in the chunk of the vendors group, -- > vendors ~ XXX js
        // The above public rules are met. The size exceeds 30kb and is referenced at least once
        test: /[\\/]node_modules[\\/]/,
        // priority
        priority: -10
      },
      default: {
        // The chunk to be extracted is referenced at least 2 times
        minChunks: 2,
        prority: -20,
        // If the current module to be packaged is the same as the previously extracted module, it will be reused instead of repackaged
        reuseExistingChunk: true
      }
    } */
  },
  // Index The hash value of a.js recorded by JS is separately packaged into the runtime file to prevent the modification of a file from changing the hash value of b file. Finally, index If the file name of application b in JS file does not change, there will be a problem
  runtimeChunk: {
    name: entrypoint => `runtime-${entrypoint.name}`
  },
  minimizer: [
    // Configure the compression scheme of the production environment: js/css
    new TerserWebpackPlugin({
      // Enable cache
      cache: true,
      // Turn on multi process packaging
      parallel: true,
      // Enable sourcemap (otherwise it will be compressed)
      sourceMap: true
    })
  ]
}

Keywords: Javascript Front-end Vue Webpack

Added by Acs on Mon, 27 Dec 2021 19:18:54 +0200