Build optimization

1. NoParse (no need to parse internally dependent packages)

For some third-party packages we introduced, such as jQuery, there is no need for WebPack to resolve its internal dependencies. You can add the noParse attribute under the Module attribute in the WebPack configuration file, and its value is a regular expression. It is used to match modules that do not need to be resolved, which can save webPack packaging time and improve packaging efficiency.

moduleNoParse: /jquery/}Copy the code

Note that you must ensure that the added package does not depend on other packages, otherwise a dependency error will be reported.

2. DllPlugin (Dynamic link Library)

The project relies on third-party packages such as React and Vue, which generally do not change the contents of packages, and it is not reasonable to build them every time a package is packaged, which can waste performance. The right thing to do is to package these third-party packages once, then reference them directly, and build them again when they need an updated version. So we only need to build our business code when we package.

The Dllplugin plugin helps extract these unmodified packages into a dynamic link library and generates a file called manifest.json that maps the DLLReferencePlugin to the relevant dependencies.

React is used as an example to extract DLLS

  1. First create a willReactExtracted to a DllwebpackThe configuration filewebpack.react.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  mode: 'development'.// import file: put in the library to be configured as a Dll
  entry: {
    react: [
      'react']},// Output file
  output: {
    // Output the file name
    filename: '[name]_dll.js'.// Output file path
    path: path.resolve(__dirname, '.. /dist'),
    // Expose the packaged results globally
    library: '[name]_dll'
  },
  plugins: [
    new webpack.DllPlugin({
      // DLL file name
      name: '[name]_dll'.// Manifest file path
      path: path.resolve(__dirname, '.. /dist/mainfest.json')]}})Copy the code
  1. configurationDllReferencePlugin

This plugin is typically configured in the main webPack configuration file. Add the following configuration under plugins. The manifest file maps the application to the DLL file to the module ID, and then references the DLL file when needed.

new webpack.DllReferencePlugin({
  // The context of the request in the manifest (or content attribute) (absolute path)
  context: __dirname,
  // Manifest file path
  manifest: path.resolve(__dirname, '.. /dist/manifest.json')})Copy the code
  1. Build and runwebpack.react.jsConfiguration files, in general you can add the command to run the script in package.json
Scripts: {"build:react": "webpack --config./build/webpack.react.js"}Copy the code

Running this command on the command line will generate the React Dll in the dist directory, as well as a mainfest.json file that contains the mapping of the import and require request to the module ID. The DLLReferencePlugin also references this file. React is then packaged so that the react_DLL file is referenced directly instead of being re-packaged.

Code optimization

The ultimate goal of code optimization is to optimize the user experience, and all kinds of compression and splitting operations should be carried out around the ultimate goal.

1. Webpack comes with optimizations

Set webpack mode to Production, and webapck will automatically optimize the following when packing production mode

  • tree shaking

Webpack removes imported but unreferenced code at packaging time, but only those introduced through the import syntax of the ES6 module system are tree shaking, reducing the size of files in production and automating the most basic optimizations

  • scope hoisting

Analyze the dependencies between modules and merge the scattered modules into a function as much as possible. Note that this optimization applies only to modules introduced through the import syntax of the ES6 module system, and only those modules that are referenced only once may be merged.

  • Code compression

All code is automatically compressed using UglifyJsPlugin.

2. CSS optimization

  • Split the CSS into separate files

Mini-css-extract-plugin can split CSS into separate files so that CSS files can be loaded asynchronously to speed up page loading and rendering.

Usage:

  1. Installing a plug-in
$ npm i mini-css-extract-plugin -D
Copy the code
  1. Modify the master configuration file to use the plug-in
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = { ... .module: {
        rules: [..., {test: /\.css$/./ / will have to use style - more than the original loader to handle is replaced by using MiniCssExtractPlugin. Loader
                // use: ['style-loader', 'css-loader'],
                use: [MiniCssExtractPlugin.loader, 'css-loader']]}},plugins: [...new MiniCssExtractPlugin({
            // The generated file name
            filename: '[name].css'}})]Copy the code
  • Compress CSS

Optimize – CSS-assets-webpack-plugin can be used to compress CSS files, but the plugin will cause the default js compression configuration of Webpack not to take effect, so you need to manually compress JS code. Js compression uses the official recommended Terser-webpack-plugin

Usage:

  1. Installing a plug-in
$ npm i optimize-css-assets-webpack-plugin terser-webpack-plugin -D
Copy the code
  1. Modify the master configuration file to use the plug-in
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = { ... .optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    }
}
Copy the code

3. JS optimization

  • Split common code

Usage: Simply add the following configuration to the master configuration file

Optimization: {
    splitChunks: {
        Chunks: 'all'}}Copy the code
  • IgnorePlugin (ignore plug-in)

There are a lot of third-party packages that are internalized and contain a lot of language packages, which are of little use to us and will only increase the size of the package. We can completely ignore these language packages to improve the construction efficiency and reduce the size of the package.

Using moment as an example, first find the folder where the language packages are in Moment, and then add the plug-in to the WebPack configuration file

The first parameter indicates the path to be ignored. The second parameter indicates the directory in which the resource is located. Any language packages introduced in this folder are ignored
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
Copy the code

The moment uses the default language English. If you want to use another language, you can manually import the required language package.

import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-CN')
Copy the code
  • Lazy loading

There are blocks of code in the page that may not need to be used when the page is initialized, but require some action from the user. If the user does not trigger the action, the code block may never be used. We can load these blocks of code that will only be used when an action is triggered on demand, rather than directly at page creation, to speed up the initial page load.

// Suppose there is a button with the id BTN in the page. When clicking this button, you need to manipulate the time
const btn = document.querySelector('#btn')
btn.onclick = e= > import(/* webpackChunkName: "moment" */ 'moment').then(module= > {
    var moment = module.default;
    moment().format('YYYY-MM-DD')})Copy the code

Since lazy loading affects the user experience, you can use magic to load dynamically imported resources when idle after the home page has finished loading, which improves page loading speed and ensures user experience.

const btn = document.querySelector('#btn')
btn.onclick = e= > import(/* webpackChunkName: "moment" *//* webpackPrefetch: true */ 'moment').then(module= > {
    var moment = module.default;
    moment().format('YYYY-MM-DD')})Copy the code

Keep up to date

Webpack gets a big performance boost with each release, and it is officially recommended to keep the release up to date.