Stone sound, do not copy do not sing

The Production pattern package comes with optimizations

The Production schema package comes with many optimizations, such as Tree Shaking, Scope reactive, code compression, and so on

tree shaking

Tree shaking refers to removing unused DEAD code from JS at packaging time. It relies on the static structural nature of the ES6 modularity specification.

  • When a module is introduced and only some functions of the module are used, only the used functions are packaged into the bundle. Other unused functions are not packaged.
  • Pay attention torequireIs dynamic import, useCommonJS modular specificationIt affects the packagingtree shakingfunction

In the case of scope promotion,

Scope will predict the result of the module, which can make the files packaged by WebPack smaller and faster. The scope hoisting is also based on ES6 modular specifications, it is by the webpack plug-ins ModuleConcateNationPlugin. The default configuration in production mode ModuleConcateNationPlugin plug-in, other patterns not open by default.

The sample

  • New SRC/model. Js

    export let a = 1
    export let b = 2
    export let c = 9
    Copy the code
  • Main.js evaluates variables exported by the model module

    import { a, b, c } from "./model.js";
    const sub = (modelA, modelB, modelC) = > ((modelA + modelB) * modelC)
    console.log("Sum of a, B, and C", sub(a, b, c));
    Copy the code
  • NPM run build to view the package result

From the above example, we can see the power of scope promotion. Through it, Webpack can deduce the result when packaging, and combine modules into a function, which greatly avoids code redundancy.

Code obfuscation and compression

In Production mode, when webPack is packaged, the code is obfuscated and compressed through the UglifyJsPlugin plug-in

CSS optimization

CSS optimization – Extract CSS code into a separate file

The previous CSS code is directly placed in the HTML style tag, when the same CSS code in multiple modules multiple pages when used, in order to improve reuse to avoid repeated compilation is best to extract the CSS code into a separate file.

Make adjustments to the current project

1. Optimize the project directory structure

2. Modify the SRC /webpack.base.js configuration to be packaged as a single page application

module.exports = {
  // 1. Specify only one entry file
  entry: "./src/main.js".// entry: {
  // index: "./src/main.js",
  // other: "./src/other.js",
  // },
  output: {
    path: path.resolve(__dirname, ".."."./dist"),
    filename: '[name].js'
  },
  plugins: [
    new HtmlPlugin(
      {
        filename: "index.html".template: "./src/index.html".// 3. Do not specify chunks either, or the CSS may have problems
        // chunks: ["index", "other"]}),// 2. Remove the HtmlPlugin that generates other.html
    // new HtmlPlugin(
    / / {
    // filename: "other.html",
    // template: "./src/other.html",
    // chunks: ["other"]
    / /}
    // ),]}Copy the code

3. Import CSS from SRC /main.js

import "./css/index.css"
import "./less/index.less"
Copy the code

MiniCssExtractPlugin

MiniCssExtractPlugin is a plug-in that extracts CSS without separate files. It generates a separate CSS file for each JS file containing CSS and supports loading CSS and sourceMap on demand

  • Install the NPM I mini-CSS-extract-plugin

  • Configure the plugin and loader

    // webpack.base.js  
    // 1. Import plug-in constructor
    const MiniCssExtract = require("mini-css-extract-plugin")  
    module.exports = {
      plugins: [
        // 2.new a MiniCssExtract plugin instance and configure the generated CSS file name
        new MiniCssExtract({
          filename: "main.css"})].module: {
      rules: [{test: /\.css$/i.// 3. Style-loader put CSS code into the style tag and replace all style-loaders with MiniCssExtract loader
          use: [MiniCssExtract.loader, 'css-loader'] {},test: /\.less$/i,
          use: [MiniCssExtract.loader, 'css-loader'.'less-loader']]}}Copy the code
  • NPM Run Build package CSS is extracted separately

CSS optimization – Automatically adds CSS property prefixes

Postcss is used to automatically add CSS attribute prefixes. Postcss requires postCSS-Loader and autoprefixer plug-ins

  • Install NPM I postCSs-loader autoprefixer

  • Configure the loader

    // webpack.base.js  
    module: {
      rules: [{test: /\.css$/i.// Configure 'postCSs-loader' on the right of CSS-loader to automatically add CSS attribute prefixes
          use: [MiniCssExtract.loader, 'css-loader'.'postcss-loader'] {},test: /\.less$/i.// Configure 'postCSs-loader' on the right of CSS-loader to automatically add CSS attribute prefixes
          use: [MiniCssExtract.loader, 'css-loader'.'postcss-loader'.'less-loader']]}}Copy the code
  • Create postcss.config.js in the project root directory

    module.exports = {
      // PostCSS is very simple and relies on plug-ins for many functions
      "plugins": [
        require('autoprefixer')]}Copy the code
  • Package. json adds the Browserslist field

    "browserslist": [
      "defaults"."not ie <= 8"."last 2 versions"."1%" >."iOS >= 7"."Android > = 4.0"
    ]
    Copy the code
  • Nom Run Build rebuilds the project

CSS optimization – CSS code compression

Optimize – CSS -assets-webpack-plugin The problem with this plugin is that webpack has js compression obliqueness enabled by default when packaged in production mode, but the plugin-optimization-csS-assets-webpack-plugin overwrites the webpack default optimization and makes JS code uncompressed. So we need to import the terser-webpack-plugin to configure the JS code compression function.

  • Install NPM I optimize- CSS-assets -webpack-plugin terser-webpack-plugin -d

  • Add a configuration node to the configuration file

    // webpack.prod.js
    // 1. Import plug-ins
    const TerserWebpackPlugin = require("terser-webpack-plugin")
    const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin")
    const prodConfig = merge(baseConfig, {
      // 2. Add the optimized configuration item
      optimization: {
        minimizer: [new TerserWebpackPlugin({}), new OptimizeCSSAssetsPlugin({})]
      }
    })
    Copy the code
  • Modify the main js

    import "./css/index.css"
    import "./less/index.less"
    let a = 20
    let b = 30
    function add(a, b) {
      return a + b
    }
    console.log("The results", add(a, b));
    Copy the code
  • NPM run build successfully compresses js/ CSS after package

JS code optimization

JS Code Splitting

Code Splitting is one of the most important features of Webpack. It can split Code into bundles and then load those files on demand and in parallel. Controlling the loading priority of these bundle resources can greatly affect the loading speed. For example, a single bundle file in a SPA application is too large, resulting in slow loading of the first screen.

There are three common ways to separate code:

  • Entrance to the starting point

    Manually configure multiple entry, throughentryConfiguration separation code
  • To prevent the repeat

    useSplitChunksPluginFor example, module A and module B both use jquery, so we need to avoid jquery being repeatedly packaged into two modules.
  • Dynamic imports separate code through module inline function calls, such as lazy loading of routes

Manually configure multiple entries

  • Install jquery NPM I jquery

  • Modify SRC /main.js and create SRC /other.js

    // main.js  
    import $ from 'jquery'
    $(function () {
      // Create a new div and insert it into the body
      $("<div></div>").html("This is the main. Js").appendTo("body")})// other.js  
    import $ from 'jquery'
    $(function () {
      // Create a new div and insert it into the body
      $("<div></div>").html("This is an other. Js").appendTo("body")})Copy the code
  • Configuring Multiple Entries

    // webpack.base.js  
    module.exports = {
      entry: {
        // The entry files are main.js/other.js respectively
        main: "./src/main.js".other: "./src/other.js"}}Copy the code
  • NPM run dev checks the packing results

    As you can see, each bundle is only a few lines of code, but the size is several hundred KB. Obviously, duplicate JQ modules have been introduced into each bundle

There are some problems with configuring multiple entries:

  • If there are repeating modules between chunks in the entry, those repeating modules will be introduced into each bundle
  • This approach is not flexible enough to dynamically split the logic at the heart of the program

Extract common code

Although the previous two bundles were divided, there was a problem of module duplication. SplitChunksPlugin extracts common code.

  • Modify the configuration file webpack.base.js

    module.exports = {
      optimization: {
        splitChunks: {
          // Remove all duplicate modules
          chunks: "all"}}}Copy the code
  • The NPM Run Build rebuild JQ module is pulled out separately

Dynamic import

In project development, the single-page application is the main application and rarely needs to configure multiple entry files. The extraction of common code is also rarely used, and dynamic import (lazy loading of routes) is often used. The CommonJS modularity specification supports dynamic imports, whereas the ES6 modularity specification is static. Dynamic import of modules can be implemented with Import (module) in Webpackage 5

import(module)

Import (Module) dynamically imports modules, which return a Promise instance that can be obtained via.then

  • Modify the SRC/main. Js

    let a = 1
    if (a === 1) {
      console.log("a", a);
      import("jquery").then(({ default: $}) = >{$("<div></div>").html("This is dynamically imported main.js").appendTo("body")})}Copy the code
  • NPM run dev Check the result

Problems with static imports

Modules packaged with static imports are loaded in when the page loads, which is very disruptive to the experience

  • Empty index. HTML

    <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Width =device-width, initial-scale=1.0"> <title>Document</title> <! - < link rel = "stylesheet" href = ". / CSS/index. CSS "> -- > < / head > < body > < button id =" BTN "> inserted into the DOM < / button > < / body > < / HTML >Copy the code
  • Modify the main js

    import $ from 'jquery'
    // Create a new node using JQ after clicking the button and insert it into the page
    document.getElementById("btn").onclick = function () {$("<div></div>").html("main.js").appendTo("body")}Copy the code
  • NPM Run Server runs the service and you can see that JQ is already loaded when the page loads and we’re not using it at this point

Benefits of dynamic import

Dynamic import allows modules to be loaded on demand (lazy loading) and only loaded when the module is actually used

  • Application changed to single entry

    // webpack.base.js  
    module.exports = {
      entry: "./src/main.js".// entry: {
      // main: "./src/main.js",
      // other: "./src/other.js"
      // }
    }
    Copy the code
  • Modify the SRC/main. Js

    document.getElementById("btn").onclick = function () {
      import("jquery").then(({ default: $}) = >{$("<div></div>").html("This is dynamically imported main.js").appendTo("body")})}Copy the code
  • NPM run dev Runs the service and the JQ module is loaded only after the button is clicked

Resolution of the code

SplitChunksPlugins splitChunksPlugins implemented by splitChunksPlugins automatically split code according to the following default configuration:

  • Public modules or component modules from under node_modules
  • Packaged code block size over 30KB (before minimum compression)
  • When loading code blocks on demand, no more than 5 requests should be sent simultaneously
  • Page initialization, the number of simultaneous requests should not exceed 3

Note: The official Demo example is Mac, and the path is a forward slash window. Use a backslash to obtain the module name!!!!

 optimization: {
    splitChunks: {
      / / to split asynchronous loading module Optional value: all (static and dynamic module are split) | initial (for static module import split);
      chunks: 'async'.// The minimum size of chunk that can be removed is 20KB
      minSize: 20000.// Webpack5 new property to prevent chunk size 0
      minRemainingSize: 0.// A module must be referenced at least once before it is split
      minChunks: 1.// The maximum number of asynchronous loading requests cannot exceed 30. The number of requests exceeding 5 is not split
      maxAsyncRequests: 30.// The maximum number of simultaneous requests sent on a page cannot exceed 30. If the number exceeds 30, the page will not be split
      maxInitialRequests: 30.// Enforce split when the module size is greater than 50KB ignoring any other restrictions
      enforceSizeThreshold: 50000.// Cache group configuration, the above configuration read after the module split, if multiple modules split into a file on the need to cache, so named cache group
      cacheGroups: {
        // Customize a cache group named Commons
        commons: {
          // Match rules
          test: /[\\/]node_modules[\\/]/.When a module matches multiple cache groups, it finally decides which cache group to pack into according to the weight
          priority: -10.reuseExistingChunk: true.// Cache group generates file names for dynamic customization
          name(module, chunks, cacheGroupKey) {
            console.log("Module path".module.identifier());
            const moduleFileName = module
              .identifier()
              // window: E:\study\basic\node_modules\jquery\dist\jquery.js
              .split("\ \")
              // mac: E:/study/basic/node_modules/jquery/dist/jquery.js
              // .split("/")
              .reduceRight((item) = > item);
            const allChunksNames = chunks.map((item) = > item.name).join('~');
            // Cache group name -[module dependent module]- module name
            return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
          },
          // Cache group generated file name write die custom
          filename: "vendors.js"
        },
        // Default cache group
        default: {
          // The module must be referenced at least twice before splitting
          minChunks: 2.priority: -20.For example, there are two modules A and B in the main entry, but the packaging of module A is referenced in module B, which may lead to repeated packaging. Module A reuseExistingChunk can reuse duplicate chunks
          reuseExistingChunk: true,}},},},};Copy the code

Improving build performance

When packaging a project, in addition to optimizing the packaging file, you can also improve build performance and reduce build time.

Ignore parsing modules (noParse)

Some third-party modules, such as LoDash and jquery, clearly know that they do not depend on other modules, so there is no need for WebPack to parse their module dependencies and waste build performance. Modules that do not need to resolve dependencies can be configured using module.noparse

  • SRC /main.js using jquery

    document.getElementById("btn").onclick = function () {
      import("jquery").then(({ default: $}) = >{$("<div></div>").html("This is dynamically imported main.js").appendTo("body")})}Copy the code
  • NPM Run Build is packaged directly without noParse, and the build time is about 3664 milliseconds

  • Configuration noParse

    // config/webpack.base.js  
    module.exports = {
      module: {
        // The jquery module is not parsed
        noParse: /jquery/.// Do not parse multiple modules
        // noParse: /jquery|lodash/}}Copy the code
  • npm run buildRebuild the project

    When noParse is configured, build time is reduced by over 300 milliseconds!! Configuring multiple noParse module projects in your project is even more significant

ignorePlugin

When introducing some third party modules, such as Moment, each one will do i18N internationalization and include many language packs. However, language packages take up space when they are packaged. If a project needs only a few languages or one language, you can ignore the other language packages. This way, the construction of the project is more efficient and the resulting file size is smaller

IgnorePlugin can ignore other modules that depend on within a module, and then import modules as needed

  • First find the language pack that Moment depends on
  • Use ignorePlugin to ignore its dependencies
  • Import dependencies manually when you need them

moment

Moment is a repository of tools for internationalizing time processing

  • Install moment NPM I moment

  • Use my moment

    // src/main.js  
    / / import my moment
    import moment from 'moment'
    // Use the Chinese language pack
    moment.locale("zh-CN")
    // Calendar time six days ago
    const time = moment().subtract(6.'days').calendar();
    console.log("time", time);
    Copy the code
  • NPM run build view the build result

Use ignorePlugin for optimization

  • findmomentInternally introduced language modules
    • View the language pack location (node_modules/moment/locale)

    • Search the require keyword in the moment entry file to see which modules are introduced internally

  • configurationignorePlugin
    module.exports = {
      plugins: [/** * IgnorePlugin: is a built-in webpack plug-in * IgnorePlugin(options) * -options: configuration objects * -resourceregExp: modules to be ignored, The locale package module in moment * -contextregexp: Use the context of the ignored module in which you are using the ignored module. The context of the language package module is the moment module */
         new Webpack.IgnorePlugin({
           // Ignore the "./locale" module
           resourceRegExp: /\.\/locale/.// Ignore the "./locale" module in moment
            contextRegExp: /moment/}})]Copy the code
  • Import the language pack module as needed

    The front byignorePluginI’ve ignoredmoment.jsAll language package modules introduced. We need to introduce language pack modules as needed in the business code
    import moment from 'moment'
    // Manually import the Chinese language package
    import 'moment/locale/zh-cn'
    moment.locale("zh-CN")
    const time = moment().subtract(6.'days').calendar();
    console.log("time", time);
    Copy the code
  • npm run buildRepackage to compare the file size before and after packaging

    Codesplit previously divided the language bundle into a separate bundle with a size of 228.KB due to its large size. throughignorePluginThe 228.kb bundle has been optimized and main.js has been reduced.

Use noParse with caution

NoParse ignores the parsing of dependencies within a module, and using noParse blindly can lead to loss of dependencies within a module

For example, ignoring the moment language package module dependency import using ignornPlugin will cause a bug if you configure Moment into noParse after importing the language package as needed. So be sure to rebuild the project after noParse is configured to see if it works properly.

When tuning a project, we should rebuild the project after each step of optimization to see if it is working properly. Don’t build your project after you’ve optimized all of your operations, in case problems occur and you can’t figure out which pace is best.

Generate a dynamically linked library (DLLPlugin)

When introducing third-party modules such as Vue, React, Angular, etc., the code of these framework modules generally does not change, but it is a waste of performance to reparse these modules every time they are packaged.

These modules can be individually packaged into a dynamically linked library through the DLLPlugin and built only once. The following only builds the business layer code to reuse the dynamic link library, which can greatly improve the construction speed.

This feature involves two plug-ins

DllPlugin

Configure the DLLPlugin package to create the DLL file using a separate Webpack configuration file, and also create a manifast. Json (this file is the DLL file instruction manual). DllReferenceolugin uses this JSON file to do the dependency mapping

  • Context (optional) : The context of the request in the manifast file. Default is the webpack file context
  • Name: specifies the public DLL function name, which must be the same as output.library
  • Path: mainfast.json Generated path

DllReferencePlugin

Configure the plug-in in the main WebPack configuration file, which automatically imports previously packaged modules by referencing previously built DLLS

  • Context: The context of the request in the mainfast file
  • Mainfast: Mainfest.json generated by the DllPlugin plugin
  • Content (Optional) : Requested mapping module ID (default: mainfest.content)
  • Name (Optional) : Exposes the name of the DLL
  • Scope (Optional) : Prefix used to access the contents of a DLL
  • SourceType (optional) : How the DLL is exposed (libraryTarget)

Here is how to configure Vue and React

Vue generates a dynamic link library

  • Install NPM I vue vue-router-s

  • Modified index. HTML

    <body>
      <div id="app">{{msg}}
        <div>
          <router-link to="/">The home page</router-link>
          <router-link to="/about">The about page</router-link>
          <router-view />
        </div>
      </div>
    </body>
    Copy the code
  • Initialize the Vue

    // src/main.js  
      // Runtime-only vue. Js: The runtime-only version cannot parse the template and must be configured with a loader
      // import Vue from 'vue'
      / / the runtime - the compiler version vue. Js
    import Vue from 'vue/dist/vue.js'
    new Vue({
      el: "#app".data() {
        return {
          msg: "1111"}}})Copy the code
  • Configure the routing

    // src/main.js   
    import VueRouter from "vue-router"
    Vue.use(VueRouter)
    // Create the Home and About components
    const Home = {
      template: "< h2 > this is the home < / h2 >"
    }
    const About = {
      template: "< h2 > this is the about < / h2 >"
    }
    // Create a route matching rule
    const routes = [
      {
        path: "/".component: Home
      },
      {
        path: "/about".component: About
      }
    ]
    // Create a route instance
    const router = new VueRouter({ routes })
    new Vue({
      el: "#app".// Mount the route
      router,
      data() {
        return {
          msg: "1111"}}})Copy the code
  • Config /webpack.vue.js config/webpack.vue.js is dedicated to packing vue buckets into Dll files

    • Configuration entry, which introduces multiple modules to be made into DLL libraries
    • Configuration exit, be sure to set the Library property to expose the packaged results globally
    • Configure plugin, set packaged DLL filename and manifest file location
      // config/webpack.vue.js  
      const path = require("path")
      const webpack = require("webpack")
      module.exports = {
        entry: {
          // Vue library entry
          vue: [
            Vue. Esm.js is used by default
            'vue/dist/vue.js'.'vue-router']},output: {
          path: path.resolve(__dirname, ".. /dist"),
          // Use placeholder syntax
          filename: "[name]_dll.js"
        },
        plugins: [
          // Package modules into DLL files through the DllPlugin
          new webpack.DllPlugin({
            // The variable name exposed by the packaged DLL file
            name: "[name]_dll".// DLL file instructions
            path: path.resolve(__dirname, ".. /dist/manifest.json")]}})Copy the code
  • Added the script for packaging DLL files

      "scripts": {
        // Package DLL files
        "build:vue": "npx webpack --config ./config/webpack.vue.js"
      }
    Copy the code
  • Execute NPM run build:vue to get the DLL file. This vue bucket is no longer packaged

  • The DLL files generated before using the dynamic link library in the project need to be registered to use the DLL files in the WebPack configuration file

    // config/webpack.base.js  
    module.exports = {
      plugins: [
        // When using DLLS, you cannot use the CleanWebpackPlugin, which will empty all dist directories such as DLLS
        // new CleanWebpackPlugin(),
        // Use DLL dependencies
        new Webpack.DllReferencePlugin({
          // Specify the DLL instruction path
          manifest: path.resolve(__dirname, ".. /dist/manifest.json")]}})Copy the code

Add-asset-html-webpack-plugin (add-asset-html-webpack-plugin, add-asset-webpack-plugin, add-asset-webpack-plugin, add-asset-webpack-plugin, add-asset-webpack-plugin

  • The installationnpm i add-asset-html-webpack-plugin -D
  • Configure the plug-in
    // webpack.base.js  
    const AddAssetHtmlWebpackPlugin = require("add-asset-html-webpack-plugin")  
    module.exports = {
      plugins: [
        // Insert resources into the packaged HTML. This plug-in must be configured after the HtmlPlugin
        new AddAssetHtmlWebpackPlugin({
          // Load DLL resources
          filepath: path.resolve(__dirname, ".. /dist/vue_dll.js"),
          // This field must be added otherwise the DLL reference path will be added with auto after packaging
          publicPath: '/',}})]Copy the code
    • NPM run build is repackaged

      For comparison, the time without DLL increased from 3701ms to 4731ms

React generates a dynamic link library

  • Install NPM I react react- dom-s

  • Modified index. HTML

    <body>
      <div id="app"></div>
    </body>
    Copy the code
  • New * * main. React. Js * *

    import React from 'react'
    import ReactDOM from 'react-dom'
    // Create an H1 virtual DOM
    const node = React.createElement("h1".null."I'm tired of studying. I want to sleep!")
    // Render the virtual DOM to the APP node via ReactDOM
    ReactDOM.render(node, document.getElementById("app"))
    Copy the code
  • Modify the import file and DLL library import path

    // config/webpack.base.js  
    module.exports = {
      entry: {
        // Use the Vue library
        // main: "./src/main.js",
        // Use the React library
        main: "./src/main.react.js",},plugins: [
        // // uses DLL dependencies
        new Webpack.DllReferencePlugin({
          // Specify the DLL instruction path
          manifest: path.resolve(__dirname, ".. /dist/manifest.json")}),// Insert resources into the packaged HTML. This plug-in must be configured after the HtmlPlugin
        new AddAssetHtmlWebpackPlugin({
          // filepath: path.resolve(__dirname, ".. /dist/vue_dll.js"),
          // Load the React DLL resource
          filepath: path.resolve(__dirname, ".. /dist/react_dll.js"),
          // This field must be added otherwise the DLL reference path will be added with auto after packaging
          publicPath: '/',}})]Copy the code
  • New packaging the react of dynamic link library webpack configuration file (webpackconfig/webpack. React. Js)

    const path = require("path")
    const webpack = require("webpack")
    module.exports = {
      mode: "production".entry: {
        // React library entry
        react: [
          'react'.'react-dom']},output: {
        path: path.resolve(__dirname, ".. /dist"),
        // Use placeholder syntax
        filename: "[name]_dll.js".// The DLL library exposes global variables for use by business modules
        library: "[name]_dll"
      },
      plugins: [
        // Package modules into DLL files through the DllPlugin
        new webpack.DllPlugin({
          // The variable name exposed by the packaged DLL file
          name: "[name]_dll".// DLL file instructions
          path: path.resolve(__dirname, ".. /dist/manifest.json")]}})Copy the code
  • Configuration package react DLL library script “build: the react” : “NPX webpack — config. / config/webpack. React. Js.” “

  • Delete dist manually and run NPM run build: React to package the React DLL library

  • Execute NPM run build to build the entire project

Multi-process packaging

Webpack works in a Node environment and is packaged in single-process mode. If many resources are packaged, it may be inefficient. You can use Thread-Loader to implement multi-process packaging.

Note: there is a time cost to start a process (about 600ms) and to communicate between processes. It is not recommended to use multi-process packaging for small projects

  • The installationnpm i thread-loader -D
  • Configure the loader
    // webpack.base.js  
    module: {
      rules:[
        {
          test: /\.js$/i,
          exclude: /(node_modules|bower_components)/,
          use: [
            / / use the thread - loader
            "thread-loader"./ / {
            // loader: "thread-loader",
            // options: {
            // // Number of started processes
            // workers: 2
            / /}
            // },
            {
              loader: 'babel-loader'.options: {
                presets: ['@babel/preset-env'].plugins: ["@babel/plugin-transform-runtime"]}}]},]}Copy the code

Browser cache

When the browser accesses the page, the resource is cached to the hard disk or memory, so that the external resources in the HTML are retrieved locally. This avoids repeating requests for resources from the server, which greatly improves efficiency.

A problem occurs when a new version of the project is developed and the updated business code goes live. Because of the browser cache, the browser does not have access to resources such as the latest JS files, which causes the page to fail to update.

It is best to separate project code and package third-party modules and business code separately. Add random hash strings to build output JS filenames by building the export placeholder syntax. So every time you package the file name of the build, every time you visit the page you access the resource from the latest file.

Placeholder syntax variable

  • Name: indicates the meta file name
  • Hash: Generates hash values randomly each time a Webpack is packaged
  • Chunkhash: Different chunks have different hash values. Different chunks may be generated in the same package
  • Contenthash: Different contents have different hash values. There may be different contents in the same chunk

Packaging analysis

After the project is built, we can analyze the packaged bundles with the help of a tool.

The result information is analyzed by packaging JSON files

  • Use –profile –json instruction to export the package information in JSON form to a JSON file “Build :analyse”: “npx webpack –profile –json > stats.json –config ./config/webpack.prod.js”

  • Execute NPM Run Build: Analyse to build the project and generate build information files

  • Open webPack’s official analysis tool and upload stats.json

    Link address: webpack. Making. IO/analyse

Configure the analysis plug-in for packaging analysis

  • Install NPM I webpack-bundle-Analyzer -d

  • Config plug-in (config/webpack.prod.js)

    // Import the bundle analysis plug-in
    const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer")
    const prodConfig = merge(baseConfig, {
    mode: "production".plugins: [
      // Initialize the plug-in
      new BundleAnalyzerPlugin()
    ]})
    Copy the code
  • After the NPM Run Build is rebuilt, an analysis service is automatically run