Statistical analysis

You must learn statistical analysis before you can optimize.

The primary analysis

Build statistics using WebPack’s built-in stats.

Package. json uses stats, configured in the scripts option:

"build:stats": "webpack --config webpack.prod.js --json > stats.json"
Copy the code

The contents of stats.json:

Velocity analysis

Use speed-measurement-webpack-plugin to see how long each loader and plug-in takes to execute.

Installation:

 yarn add speed-measure-webpack-plugin --dev
Copy the code

configuration

// Import and instantiate
const SpeedMeasureWebpackPlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasureWebpackPlugin();

// Exports package using SMP
module.exports = smp.wrap({ ... loader, ... plugins });Copy the code

Loader and plug-in speed analysis:

File size analysis

Webpack-Bundle-Analyzer

 yarn add webpack-bundle-analyzer --dev
Copy the code

Configuration:

 const WebpackBundleAnalyzer = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

// Configure it in the plugin
plugins:[
	new WebpackBundleAnalyzer(),
]
Copy the code

When the build is complete, the size will be displayed on port 8888:

Problems that can be analyzed:

  • Dependent third-party module file size
  • The size of component code in the business.

Use a higher version of WebPack

Reasons for optimization:

  1. V8 optimizations (for of instead of forEach, Map and Set instead of Object, includes instead of indexOf);
  2. The faster MD4 hash algorithm is used by default;
  3. Webpacks AST can be passed directly from loader to AST, reducing parsing time;
  4. Use string methods instead of regular expressions.

Using thread-loader to resolve resources:

How it works: Each time WebPack parses a module, thread-Loader assigns it and its dependencies to worker threads. Installation:

yarn add thread-loader --dev
Copy the code

For example, to parse js, configure:

{
  test: /\.js$/,
  exclude: /node_modules/.// "eslint-loader"
  use: [{ loader: "thread-loader".options: { workers: 3}}].use: ["babel-loader"],},Copy the code

Parallel compression

Use the terser-webpack-plugin and turn on the PARALLEL parameter. Installation:

const TerserWebpackPlugin = require("terser-webpack-plugin");
Copy the code

In Optimization, configure:

optimization: {
  minimizer: [
    new TerserWebpackPlugin({
      parallel: 4./ / or true
      cache:true})],},Copy the code

Use DLLPlugin for subcontracting

Package the react, react-dom, redux, React-Redux and business base packages into one file.

Method: Use DLLPlugin to subcontract, and DllReferencePlugin to refer to manifest.json.

Configuration webpack. DLL. Js:

const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  // The module to be extracted into a DLL file
  entry: { library: ["react"."react-dom"]},output: {
    // The directory of the output file
    path: path.join(__dirname, "build/library"),
    // The generated DLL file
    filename: "[name].dll.js".// The exposed global variable
    output: "[name]_[chunkhash]",},plugins: [
    new CleanWebpackPlugin(),
    new webpack.DllPlugin({
      // The location where the json file is stored
      path: path.join(__dirname, "build/library/[name].json"),
      // The global variable name of the DLL file must be the same as output.output
      name: "[name]_[chunkhash]",})]};Copy the code

In package.json, configure the webpack.dll.js file startup command:

  "scripts": {
    "dll": "webpack --config webpack.dll.js"
  },
Copy the code

Running Webpack will output two files:

The contents of the library.json file:Webpack indexes each library so that subsequent DLL users can read the file and refer to it directly by id.

Configuration of plugins in webpack.prod.js

new webpack.DllReferencePlugin({
  manifest: require("./build/library/library.json"),}),Copy the code

The index file is significantly smaller after startup:

Set the import DLL file in the HTML template file:

The cache

Objective: To speed up the secondary build

Cache idea: Objective: To improve the speed of secondary build

  • Babel-loader Enables cache
  • The terser-webpack-plugin enables caching
  • Use the cache-loader or hard-source-webpack-plugin

I suggest using the hard-source-webpack-plugin, because it is convenient and can be imported directly into the plugin. The installation

yarn add hard-source-webpack-plugin --dev
Copy the code

Configuration:

const HardSourceWebpackPlugin = require("hard-source-webpack-plugin");

plugins:[
	new HardSourceWebpackPlugin(),
]
Copy the code

First packing:Second packing:

You can see that there’s a significant reduction in time.

Narrow build goals

When packaging, build as few modules as possible, such as babel-Loader does not parse node_modules.

Reduce file search scope

Resolve

Webpack will start from the configured entry module to find all dependent modules. Resolve configuates how Webpack will find the corresponding file for the module. Webpack has built-in JavaScript modularized syntax parsing capabilities. By default, the rules are found in the modularized standard, but you can modify the default rules to suit your needs.

Resolve arguments:

  1. The Alias configuration item uses aliases to map the original import path to a new import path. For example, use the following configuration:
resolve:{
  alias: {components: './src/components/'}}Copy the code

When you import with import Button from ‘components/ Button ‘, the alias equivalent is actually replaced with import Button from ‘./ SRC /components/ Button ‘. 2. MainFields, Webpack will decide which code is preferred based on the configuration of mainFields, mainFields default is as follows:

  mainFields: ['browser'.'main']
Copy the code
  1. Extensions: If the import statement does not have a file suffix, Webpack will automatically add the suffix and try to access the file to see if it exists. Resolution.extensions configures the list of suffixes to use during the attempt. The default is:
  extensions: ['.js'.'.json']
Copy the code
  1. Modules: resolve.modules ConfigureWebPack which directories to look for third-party modules. The default value is [‘node_modules’], which means to go to the current directory./node_modules directory and then go to the next directory if you can’t find the module. Find/node_modules.

Comprehensive configuration:

resolve: {
  alias: {
    react: path.resolve(
      __dirname,
      "./node_modules/react/umd/react.production.min.js"
    ),
    "react-dom": path.resolve(
      __dirname,
      "./node_modules/react-dom/umd/react-dom.production.min.js"),},extensions: [".js"].mainFields: ["main"],},Copy the code

Delete unnecessary CSS

Use PurifyCSS to iterate through the code and identify the CSS classes that have been used. Use purgecss-webpack-plugin and mini-css-extract-plugin in combination. It removes CSS classes that are not being used

Installation:

yarn add purgecss-webpack-plugin --dev
Copy the code

Configuration:

const PurgecssPlugin = require("purgecss-webpack-plugin");

plugins:[
	// Use glob.sync to traverse files in the specified directory, matching only files, not directories
    new PurgecssPlugin({
      paths: glob.sync(`${path.join(__dirname, "src")}/ * * / * `, { nodir: true})}),]Copy the code

Image compression

Use image-webpack-loader. Url-loader and image-webpack-loader cannot be used together. Otherwise, images cannot be displayed. Make sure you write ‘file-loader’ first to use ‘image-webpack-loader’ and there are various configurations to adjust the quality of the images you want to compress.

Tip: Using Webp will greatly reduce the size, but ios does not support this format, resulting in no images on ios.

{
  test: /\.(png|jpe? g|gif|svg)(\? . *)? $/,
  use: [
    {
    loader: 'file-loader'.options: {
        name: '[name].[hash:7].[ext]'.outputPath: 'mobile/img'}}, {loader: 'image-webpack-loader'.options: {
        mozjpeg: {
          progressive: true.quality: 50
        },
        // optipng.enabled: false will disable optipng
        optipng: {
          enabled: false,},pngquant: {
          quality: [0.5.0.65].speed: 4
        },
        gifsicle: {
          interlaced: false,},/ / ios does not support
        // webp: {
        // quality: 100
        // }}}}]Copy the code

Dynamic Polyfill

Principle of the Polyfill Service: Identify User agents, deliver different Polyfills, and return only the polyfills required by users.

Introduce dynamic polyfills in HTML templates.

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
Copy the code

Volume optimization strategy summary

  1. Scope Hoisting

  2. Tree-shaking

  3. Image compression

  4. Dynamic Polyfill