Some configuration optimization and solutions of webpack

Time:2020-12-6

start

The official website is the best learning material, this article skips the introduction configuration these contents, arranges some commonly used configuration points.

Dependency queries in the webpack packaging process:

  • Es2015 import statement
  • Commonjs require() statement
  • Amd define and require statements
  • The @ import statement in the CSS / sass / less file.
  • Style (URL (…)) or HTML file(<img src=...>)Picture links in

Starting with entry, webpack recursively builds aDependency graphTo package all these modules in the dependency graph into a small number of bundles into the / dist or / build directory.

1、 Module loading

Webpack starts from the entry by default. All files are modules. Various types of files (JS, CSS, sass, JPG, PNG…) are processed through module configuration.

Loading different types of modules in the webpack dependency graph requires different loaders. If there is no loader, there will be“ModuleParseError: Module parse failed“And so on.

Need to be in module.rulesFor example, when loading CSS and images, the loader installation and configuration are as follows:

npm install --save-dev style-loader css-loader file-loader
// webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: ['style-loader','css-loader']
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: ['file-loader']
        }
      ]
    }
  };

When a non JS module is encountered in the packaging, themodule.rulesMatch the file suffix in the rule, and then use the Rules.use The specified loader parses the file.The use loader can be chained and applied to modules from right to left

You can try to package custom file types by installing and configuring the corresponding preprocessor.

Ignore matching files

One scenario is that the resources that the project depends on do not need to be loaded and parsed, such as some map API or JS library.

It can be used at this timemodule.noParseTo prevent webpack from parsing files that match regular expressions and ignore import, require, define and other import mechanisms in the files, the configuration method is as follows:

module: {
    noParse: /jquery|lodash/,
    
    //Starting with webpack 3.0, you can use functions as follows:
    // noParse: function(content) {
    //   return /jquery|lodash/.test(content);
    // }
  }

Ignoring large libraries can improve build performance.

2、 Optimize CSS related configuration

2.1 postcss preprocessing

Postcss is a CSS preprocessing tool, which can help us to add prefix (autoprefixer), stylelint to the properties of CSS3, and use the new features of CSS (postcss cssnext) in advance. More importantly, it can realize the modularization of CSS and prevent CSS style conflicts.

To install postcss loader and some plug-ins of postcss:

npm i -D postcss-loader
npm i -D autoprefixer postcss-cssnext

You can set multiple plug-ins for the postcss loader:

rules: [
      {
        test: /\.(sc|c|sa)ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader',
          {
            loader: "postcss-loader",
            options: {
              ident: 'postcss',
              sourceMap: true,
              plugins: loader => [
                require('autoprefixer')(),
                require('postcss-cssnext')()
              ]
            }
          }
        ]
      }
    ]

Postcss also has many rich plug-ins to use.

2.2 style split extraction

In the production environment, the style sheet is separated into a separate file, so that each JS file containing CSS will create a CSS file to support loading CSS on demand.

Webpack4 uses the mini CSS extract plugin plug-in splitting style. Before webpack3, the extract text webpack plugin plug-in can be used

npm i -D mini-css-extract-plugin

Using mini CSS extract plugin, you can no longer inject into HTML with style loader. In addition to modifying the module configuration, you also need to modify the plugins configuration

// webpack.product.config.js
  module: {
    Rules: [// rule array, modify the creation method of modules
      {
        Test: / \. (sc| c| SA) ss $/, // regular expression, processing SCSS sass CSS
        use: [
          {
              MiniCssExtractPlugin.loader,
              options: {
              //You can specify a publicpath here
              //Default use webpackOptions.output Publicpath in
              publicPath: '../'
             }
          },
          'css-loader',   
  //...        
  plugins: [
    new MiniCssExtractPlugin({
      "// the final output file name '"
      chunkFilename: '[id].css'
    })
  ]

Where name is the configuration output.filename When the name,
Can be configured pakeage.json Use — config to specify the execution script of webpack

 "scripts": {
    "build": "npx webpack",
    "dist": "npx webpack --config webpack.product.config.js"
  }

Add dist after packaging/ main.css However, the style in html is invalid because there is no style injection, so you need to import it manually in HTML main.css Documents.

Note that this plug-in should only be used in mode: ‘production’ configuration, and style loader cannot be used in loaders chain, especially HMR at development time is not supported.

For JS code splitting, you can use the Commons chunkplugin plug-in, and the configuration method is similar.

2.3 file compression

Webpack4 can use the plug-in optimize CSS assets webpack plugin to compress files. Note that webpack4 has the minizer configuration item:

npm i -D optimize-css-assets-webpack-plugin
// webpack.product.config.js
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
//...
  optimization: {
    Minizer: [new optimizecss assetsplugin ({})] // compress CSS file
  },
  plugins: [
    New minicssextractplugin ({// split CSS)
      filename: "[name].css",
      chunkFilename: "[id].css"
    }),
  ],
 }

Similarly, compression JS also needs a plug-in uglifyjs webpack plugin. These compression plug-ins need a prerequisite: mode: ‘production’:

npm i -D uglifyjs-webpack-plugin
// webpack.product.config.js
+Const uglifyjsplugin = require ('uglifyjs webpack plugin '); // compress JS

module.exports = {
  ...
  optimization: {
    minimizer: [
+New uglifyjsplugin ({// compressed JS)
        cache: true,
        parallel: true,
        sourceMap: true // set to true if you want JS source maps
      }),
      New optimizecss assetsplugin ({}) // compress CSS file
    ]
  }
  ···
};

It should be noted that if there is no bable compatible ES6 syntax, “error unexpected token” will be reported.

3、 Image processing and optimization

3.1 loading images and fonts

Use file loader to import files

npm install --save-dev file-loader
module.exports = {
  ...
  module: {
    rules: [ 
      ...
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ['file-loader']
      }
      ···
    ]  
  } 
}     

Since custom fonts may be referenced in CSS, the processing is also consistent with the picture.

test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [ 'file-loader' ]

3.2 compressed images

File loader copies the image to dist directory and updates the reference path. Further, use image webpack loader to compress and optimize the image. Install and configure according to the NPM official website document

npm install image-webpack-loader --save-dev
module.exports = {
  ...
  module: {
    rules: [ 
      ...
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ['file-loader',
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65
              },
              // optipng.enabled: false will disable optipng
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: '65-90',
                speed: 4
              },
              gifsicle: {
                interlaced: false,
              },
              // the webp option will enable WEBP
              webp: {
                quality: 75
              }
            }
          }
        ]
      }
     ···
    ]  
  } 
}

Content length of the original image: 557478, about 557k, after repackaging and compressing, 171k

3.3 small image processing reduces HTTP requests for Base64

The function of URL loader is similar to file loader. It can package the file corresponding to URL address into the data URI scheme of Base64 to improve the access efficiency. The codes of images and hyperlinks encoded by Base64 are as follows:

<img />

<img />

For relatively small images, they can be directly packaged into Base64, thus reducing the number of HTTP requests. In the latest version of browsers, especially the mobile terminal, the compatibility with Base64 is very good, so you can rest assured to use it.

npm install --save-dev url-loader
module.exports = {
  ...
  module: {
    rules: [ 
      ...
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          // 'file-loader',
          {
            Loader: 'URL loader', // optimize the image to Base64 according to the size of the image
            options: {
              limit: 10000 // 10KB
            }
          },
          ···
        ]
      }
      ···
    ]  
  } 
}

4、 Solving cache problems

4.1 hash name of configuration file

Because of the cache policy of the browser, if we do not change the file name of the resource when deploying the new version, the browser may think that it has not been updated and will use its cached version. Therefore, after packaging the new version, the browser may still use the previous file.

One way to solve the problem of cache is to modify the file name, and update the file name every time the package file is packaged. The hash name of the configuration file in the output and plugins for managing the output:

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'main.[hash].js',
    path: path.resolve(__dirname, './dist')
  },
  ···  
  plugins: [
    New minicssextractplugin ({// split CSS)
      File name: '[name]. [hash]. CSS', // set the final output file name
      chunkFilename: '[id].[hash].css'
    })
  ],
  ···  
};

Modify the file name: ‘[name]. [hash]. CSS’

> npx webpack --config webpack.product.config.js
Hash: 10c0c7348792960894f6
Version: webpack 4.30.0

Then dist / main.10c0c7348792960894f6.css appears.

4.2 file hash name injection

When splitting CSS or JS into separate files, html is imported manually, but the files generated by hash are different each time. How to import them automatically?

With the htmlwebpack plugin plug-in, the packaged CSS or JS file reference can be directly injected into the HTML templateSo you don’t have to manually modify the file reference each time.

npm i -D html-webpack-plugin
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
···
module.exports = {
  mode: 'production',
  ···  
  plugins: [
    ···
+   new HtmlWebpackPlugin({
      Title: 'learn webpack' // default: webpack app
      filename: ' index.html ', // the final generated file, default value:' index.html '
      template:  path.resolve (E) dirname, 'src/ index.html ', // template
      minify: {
        Collapsewhitespace: true, // collapse white space
        Removecomments: true, // remove comments
        Removeattributequotes: true // remove quotation marks of attributes
      }
    })
  ],
  ···  
};

You can create a new Src in the/ index.html As a template, execute the packing command:

> npm run dist

> [email protected] dist /Users/TJing/Documents/webProjects/testWebpack
> npx webpack --config webpack.product.config.js

Hash: b6f4a880e0371e2f8ad3

Finally, main.b6f4a880e0371e2f8ad3.css, main.b6f4a880e0371e2f8ad3.js and index.html In this case, the html is automatically injected with CSS and JS:

<!DOCTYPE html>
<html lang=en>
<head>
  <meta charset=UTF-8>
  <title></title>
  <link href=main.b6f4a880e0371e2f8ad3.css rel=stylesheet>
</head>
<body>
<script type=text/javascript src=main.b6f4a880e0371e2f8ad3.js></script>
</body>
</html>

4.3 clean up dist package directory

After each compilation, the / dist folder will save the generated files, especially after the hash value of the configuration file. It is generally recommended to clean up the / dist folder before each build.

Clean webpack plugin is a popular management plug-in. The installation and configuration are as follows:

npm i -D clean-webpack-plugin
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  mode: 'production',
···  
  plugins: [
+   new CleanWebpackPlugin()
      ...
  ],
···  
};

5、 Development assistance

5.1 sourse map source tracking

Webpack packages three source files (A.js, B.js, and c.js) into a bundle( bundle.js )In the development environment, it is very difficult to debug to the original development code. At this time, we have to use the source map to solve the problem of inconsistency between the development code and the actual running code.

Set source map in devtool to enhance the debugging process, and source map type gate.

// webpack.config.js

  module.exports = {
    entry: './src/index.js',
    // ...
    devtool: 'inline-source-map',
  };

You can also use the sourcemapdevtoolplugin plug-in to replace the devtool option for more fine-grained configuration;

For style debugging, webpack will package CSS and sass modules into the style module. Both CSS loader and sass loader can enable sourcemap through the options setting.

// webpack.config.js
    Rules: [// rule array, modify the creation method of modules
      {
        Test: / \. (sc| c| SA) ss $/, // regular expression, processing SCSS sass CSS
        // use: ['style-loader', 'css-loader','sass-loader']
        use: ['style-loader',
          {
          loader: 'css-loader',
          options: {
            sourceMap: true}},
          {
          loader: 'sass-loader',
          options: {
            sourceMap: true}}]
      }
    ]

5.2 — watch automatic compilation

It is too troublesome to compile manually after each modification. The simplest way to solve this problem is to start watch to monitor the update and compile automatically.

You can add — watch to start compiling

"scripts": {
    "watch": "npx webpack --watch --config webpack.dev.js",
    ···
  },

After adding — watch, manually refresh the browser page after each modification, and you can see the updated content. But how to automatically update the changes without refreshing the page?

5.3 hot update of webpack dev server

Using webpack dev server is to create a simple web server that can be reloaded in real time.

npm install --save-dev webpack-dev-server

Configuration is only used in the development environment. In addition to configuring devserver attribute, two plug-ins need to be added to plugins

const webpack = require('webpack');

module.exports = {
  mode: 'development',
  Devtool: 'inline source map', // the sourcemap of JS
  devServer: {
    contentBase: './dist',
    hot: true,
    port: 9000
  },
  plugins: [
    new  webpack.NamedModulesPlugin (), // easier to view (patch) dependencies
    new  webpack.HotModuleReplacementPlugin () // replace plug-in
  ]
 ···

If you execute the following command, the http://localhost : 9000 / see the main page. Note that the files compiled with webpack dev server are directly in memory and will not be output to the dist directory, but files in the dist directory can be used.

npx webpack-dev-server --config webpack.dev.js

Other configurations in the official dev server website:

devServer: {
  Clientloglevel: 'warning' // possible values are none, error, warning or info (default value)
  Hot: true, // enable the module hot replacement feature of webpack, which needs to be coordinated with: webpack.HotModuleReplacementPlugin plug-in unit
  contentBase:   path.join (E) Dirname, "dist"), // tells the server where to provide the content. By default, the current working directory will be used as the content providing directory
  Compress: true, // gzip compression is enabled for all services
  Host: '0.0.0.0', // specifies to use a host. The default is localhost. If you want 0.0.0.0 to be accessible outside the server
  Port: 8080, // port
  Open: true, // open browser
  Overlay: {// whether to override the error message on the page line when an error or warning occurs.
    warnings: true,
    errors: true
  },
  Publicpath: '/', // the package files under this path can be accessed in the browser.
  Proxy: {// set proxy
    "/ API": {// to access the request at the beginning of the API, it will jump to the following target configuration
      target: "http://192.168.0.102:8080",
      pathRewrite: {"^/api" : "/mockjsdata/5/api"}
    }
  },
  Quiet: true, // necessary for friendlyerrorsplugin. After quiet is enabled, nothing except initial startup information will be printed to the console. This also means that errors or warnings from webpack are not visible in the console.
  Watchoptions: {// control options related to monitoring files
    Poll: true, // webpack uses the file system to get notification of file changes. In some cases, it will not work properly. For example, when using network file system (NFS). Vagrant also has a lot of problems. In these cases, use polling. Poll: true. Of course, poll can also be set to milliseconds, for example: Poll: 1000
    ignored: /node_ Modules /, // ignore monitored folder, regular
    Aggregatetimeout: 300 // default. When the first file is changed, the delay will be increased before rebuilding
  }
}

If you want to review the basic configuration of webpack, you can start with the official website guide. If you want to know more complex and flexible functions, you can add various plug-ins. If you are interested in writing a loader yourself, you can send a 666 to you

Some configuration optimization and solutions of webpack

Recommended Today

Regular expression sharing for checking primes

This regular expression is shown as follows: Regular expressions for checking prime numbers or not To use this positive regular expression, you need to convert the natural number into multiple 1 strings. For example, 2 should be written as “11”, 3 should be written as “111”, 17 should be written as “11111111111”. This kind of […]