1.1 Optimizing Loader Configuration

1.1.1 the include and exclude

    module:{
        rules:[
            {
                 test:/\.js$/,
                 use:['babel-loader? cacheDirectory'],
+                include:path.resolve(__dirname,'src'),
+                exclude:/node_modules/
            }
        ]
    }
Copy the code

1.1.2 resolve. Modules

resolve: {
        modules: [path.resolve(__dirname, 'node_modules')]},Copy the code

1.1.3 resolve. MainFields

MainFields is used to configure third-party modules to use that entry file isomorphic-fetch

  • When target is Web or webworker, the value is [“browswer”,”module”,”main”]
  • [“module”,”main”] js resolve: {
  • mainFields:[‘main’] }, “`

1.1.4 resolve. Alias

The resolve.alias configuration item maps the original import path to a new import path through an alias. This optimization affects the use of tree-shaking to remove invalid code

alias: {
            'react': path.resolve(__dirname, './node_modules/react/cjs/eact.production.min.js')}Copy the code

1.1.5 resolve. Extensions

The default extension is extensions: [‘.js’, ‘.json’]

  • Keep the suffix list as small as possible
  • The highest frequency is going forward
  • Add suffixes to export statements whenever possible
resolve: {
+        extensions: ['js']},Copy the code

1.1.5 module. NoParse

The module.noParse configuration allows Webpack to ignore recursive parsing of files that are not modularized

    module: {
+        noParse: [/react\.min\.js/]
    }
Copy the code

Omitted files should not contain modular statements such as import, require, define, etc

2.DLL

DLL files are called dynamic link libraries. A dynamic link library can contain functions and data called by other modules

  • Separate the base modules into a separate dynamic link library
  • When the module to be imported is in the dynamic link library, the module cannot be packaged again, but go to the dynamic link library to obtain the DLL-plugin

2.1 define the Dll

  • DllPlugin plugin: used to package one dynamic link library after another
  • DllReferencePlugin: Introduce the DllPlugin plugin wrapped dynamic connection library into the configuration file
module.exports = {
    entry: {
        react: ['react'}, output: {path: path.resolve(__dirname,'dist'),
        filename: '[name].dll.js'// Print the name of the dynamically linked library file library:'_dll_[name]'}, plugins: [new webpack.dllplugin ({name:'_dll_[name]'Json path: path.join(__dirname,'dist'.'[name].manifest.json')]}})Copy the code
webpack --config webpack.dll.config.js --mode production
Copy the code

2.2 Using dynamic Link Library Files

plugins: [
+        new webpack.DllReferencePlugin({
+            manifest: require(path.join(__dirname, 'dist'.'react.manifest.json')), +})],Copy the code
webpack --config webpack.config.js --mode development
Copy the code

3. HappyPack

HappyPack allows Webpack to split tasks into multiple sub-processes for concurrent execution, which then send the results to the main process. happypack

npm i happypack@next -D
Copy the code
module: {
        rules: [{
            test: /\.js$/, // Transfer the processing of.js files to the HappyPack instance whose id is Babel.'happypack/loader? id=babel',
            include: path.resolve(__dirname, 'src'), exclude: /node_modules/}, {// Pass the processing of the. CSS file to the HappyPack instance whose ID is CSStest: /\.css$/,
+           use: 'happypack/loader? id=css',
            include: path.resolve(__dirname, 'src')
        }],
        noParse: [/react\.min\.js/]
    },
Copy the code
New HappyPack({id: {HappyPack})'babel'Loaders: [{loader:} loaders: [{loader:] loaders: [{loader:] loaders: [{loader:]'babel-loader',
                query: {
                    presets: [
                        "env"."react"
                    ]
                }
            }]
        }),
        new HappyPack({
            id: 'css',
            loaders: ['style-loader'.'css-loader'], threads: 4, // starts several sub-processes to handle this type of file verbose:true})],Copy the code

4. ParallelUglifyPlugin

ParallelUglifyPlugin enables serial compression of JS files to enable parallel execution of multiple child processes

npm i -D webpack-parallel-uglify-plugin
Copy the code
New ParallelUglifyPlugin({workerCount: 3, // enable several sub-processes to perform concurrent compression. The default is the number of CPU cores currently running on the computer minus 1 uglifyJS: {output: {beautify:false// No need to format comments:false// do not keep comments}, compress: {warnings:falseDrop_console: // UglifyJs does not print a warning when deleting code that is not used:trueCollapse_vars // Delete all 'console' statements as collapse_varstrue// Inline variable reduce_vars that are defined but used only once:true}},}); // Extract static values that occur multiple times but are not defined as variables to reference.Copy the code

5. The server automatically refreshes

We can listen for changes to local source files, automatically rebuild the code to work, and then refresh the browser

5.1 File Listening

+ watch: trueWatchOptions: {+ ignored: /node_modules/, + aggregateTimeout: Poll: poll: 1000 poll: 1000 poll: 1000 poll: 1000 poll: 1000 poll: 1000 poll: 1000 poll/secondCopy the code

5.2 File monitoring process

  • Webpack periodically retrieves the update time of the file and compares it with the last saved time. If the file is inconsistent, it has changed. Poll is used to configure the number of times the file is asked per second
  • When the detected file does not change any more, it is cached and waits for a period of time before notifying the listener that the wait has passedaggregateTimeoutconfiguration
  • Webpack only listens for files that Entry depends on
  • We need to minimize the number of files that need to be listened to and the frequency of checks, although a decrease in frequency will lead to a decrease in sensitivity

5.3 Automatically Refreshing the Browser

    devServer: {
        contentBase: './dist',
+        inline: true
    },
Copy the code

Webpack listens for file changes, and webpack-dev-server refreshes the browser. These files are packaged in chunk, and they initiate WebSocket connections to the server on behalf of the client

+ [19] (webpack)-dev-server/client/overlay.js 3.58kib {0} [built] + [21] (webpack)-dev-server/client/socket.js 1.05kib {0} [built] + [22], / node_modules/loglevel/lib/loglevel js 7.68 KiB {0} [built] + [24] ./node_modules/strip- ANSI /index.js 161 Bytes {0} [built] + [31]./node_modules/url/url.js 22.8kib {0} [built] + [32] (webpack)-dev-server/client? http://localhost:8080 7.75 KiB {0} [built] + [33] multi (webpack)-dev-server/client?http://localhost:8080./ SRC /index.js  40 bytes {0} [built]Copy the code

5.4 Hot Replacement of modules

Hot Module Replacement allows you to update only the specified Module without refreshing the entire web page. The principle is that when a source code changes, the changed Module is recompiled and the corresponding old Module in the browser is replaced with the new output Module

  • Faster response, shorter time
  • The running state of the web page can be preserved without refreshing the web page
    devServer: {
+        hot:true
    }
Copy the code
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
   [0] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js 52 bytes {main} [built]
[./node_modules/webpack/hot/dev-server.js] (webpack)/hot/dev-server.js 1.66 KiB {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 77 bytes {main} [built]
Copy the code
if (module.hot) {
    module.hot.accept('./index.js'.function () {
        console.log('accept index.js');
    });
}
Copy the code

Optimized module hot replace browser log

plugins: [
+        new webpack.NamedModulesPlugin(),
+        new webpack.HotModuleReplacementPlugin(),
]
Copy the code
  • Listen for fewer files
  • Ignore files in the node_modules directory

6. Differentiate your environment

When developing web pages, there are usually multiple operating environments, such as:

  • An environment that facilitates development and debugging during development.
  • Publish online to the user’s operating environment.

6.1 Environment Differences

  • The code on the line is compressed
  • The development environment may print logs that only the developer can see
  • The back-end data interface may differ between the development environment and the online environment

6.2 How to Use it

if(process.env.NODE_ENV == 'production'){
     console.log('Production environment');
}else{
    console.log('Development Environment');
}
Copy the code

Webpack packs the Process module when you use it

+ new webpack.DefinePlugin({
+             'process.env': {
+                 NODE_ENV:JSON.stringify('production') +} +}),Copy the code

The reason for wrapping json.stringify around the string when defining the value of an environment variable is that the value of the environment variable needs to be a string wrapped in double quotes, and json.stringify (‘production’) is exactly equal to ‘”production”‘.

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
})
Copy the code

6.3 Three types of differentiated environmental documents

  • Use the NPM command
  • Distinguish Webpack-Merge by environment variables
  • In-code differentiation

7. CDN

CDN is also called content distribution network. By deploying resources around the world, users can access resources from the nearest server according to the principle of proximity, thus accelerating the acquisition speed of resources.

  • HTML files are not cached, put on their own server, close the cache of their own server, static resources URL becomes the address pointing to the CDN server
  • The CDN and cache are enabled for static files such as JavaScript, CSS, and images, and the file names have HASH values
  • In order to load parallel without blocking, different static resources are allocated to different CDN servers
    output: {
        path: path.resolve(__dirname, 'dist'),
+        filename: '[name]_[hash:8].js',
+        publicPath: 'http://img.zhufengpeixun.cn'
    },
Copy the code

8.Tree Shaking

Tree Shaking can be used to weed out dead code that doesn’t work in JavaScript. It relies on static ES6 modularity syntax, such as importing and exporting through import and export.

Use a Tree

  1. Do not compile ES6 modules
    {
                     loader: 'babel-loader',
                     query: {
                         presets: [
                             [
    +                               "env", {
    +                                   modules: false// Turn off the Babel module conversion function, leaving the original ES6 modular syntax +}],"react"]}}Copy the code
    webpack --display-used-exports
    Copy the code
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

 plugins: [
+   new UglifyJSPlugin()
 ]
Copy the code
webpack --display-used-exports --optimize-minimize
webpack --mode  production
Copy the code

9. Extract common code

9.1 Why do I need to extract common Code

Large sites have multiple pages, and each page contains a lot of common code because it uses the same technology stack and style code, which can be problematic if all of them are included

  • The same resources are loaded repeatedly, wasting user traffic and server cost;
  • Too many resources need to be loaded on each page. As a result, the first screen of a web page loads slowly, affecting user experience. This can be optimized if common code is separated into separate files and loaded, reducing network traffic and server costs

9.2 How Can I Extract data?

  • Base class library for long-term caching
  • Common code between pages
  • Each page generates a separate file

How to use common-chunk-and-vendor-chunk

entry: {
        pageA: './src/pageA',
        pageB: './src/pageB'
},

optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    chunks: "initial",
                    minChunks: 2,
                    maxInitialRequests: 5, // The default limit is too small to showcase the effect
                    minSize: 0 // This is example is too small to create commons chunks
                },
                vendor: {
                    test: /node_modules/,
                    chunks: "initial",
                    name: "vendor",
                    priority: 10,
                    enforce: true}}}},Copy the code

10. Start the Scope collieries

Scope collieries can make the code files packaged by Webpack smaller and run faster. It is also called “Scope promotion”, which is a new feature introduced in Webpack3.

  • The code size is smaller because function declaration statements generate a lot of code
  • Hello.js has a smaller memory overhead at run time as the code creates less scoped functions
export default 'Hello';
Copy the code
import str from './hello.js';
console.log(str);
Copy the code
var util = ('Hello');
console.log(util);
Copy the code

Instead of two functions, there is one, and the content defined in Hello.js is injected directly into main.js

const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin'); Module.exports = {resolve: {// ES6 modules in Npm are preferred by jsNext :main mainFields: ['jsnext:main'.'browser'.'main']}, plugins: [/ / open the Scope Hoisting new ModuleConcatenationPlugin ()],};Copy the code
--display-optimization-bailout
Copy the code

11. Code separation

Code separation is one of the most compelling features of WebPack. This feature enables you to separate code into different bundles and load these files on demand or in parallel. There are three common ways to separate code:

  • Entry starting point: Manually detach code using the Entry configuration.
  • Avoid duplication: use splitChunks to re-chunk and separate chunks.
  • Dynamic import: Separation of code through inline function calls to modules.

11.1 Multiple Entrances

`entry: {
  index: './src/index.js',
  another: './src/another-module.js'
}
Copy the code

11.2 Preventing Duplication

SplitChunks can extract common chunks into a newly generated chunk. common-chunk-and-vendor-chunk

optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    chunks: "initial",
                    minChunks: 2
                },
                vendor: {
                    test: /node_modules/,
                    chunks: "initial",
                    name: "vendor",}}Copy the code

11.3 Dynamic Imports and Lazy Imports

Load only the code corresponding to the function that the user currently needs. This is also known as on-demand loading. When optimizing a single-page application for on-demand loading, the following principles are generally adopted:

  • The functions of the website are divided, one chunk for each category
  • Load the functions required by opening the page for the first time and show them to users as soon as possible
  • Some function points that rely on a lot of code can be loaded on demand
  • Split code needs an on-demand loading opportunity
document
    .getElementById('clickMe')
    .addEventListener('click', () => {
        import (/*webpackChunkName:"alert"* /'./alert').then(alert => {
            console.log(alert);

            alert.default('hello');
        });
    });
Copy the code
loaders: [
                {
                    loader: 'babel-loader',
                    query: {
                        presets: ["env"."stage-0"."react"]}}]Copy the code

12. Webpack dev – middleware plug-in

The webpack-dev-middleware plugin monitors and compilers changes to files. It works with webpack-hot-middleware. Webpack-dev-middleware Webpack-hot-middleware

const path = require("path")
const express = require("express")
const webpack = require("webpack")
const webpackDevMiddleware = require("webpack-dev-middleware")
const webpackConfig = require('./webpack.config.js')
const app = express(),
            DIST_DIR = path.join(__dirname, "dist"Use (webpackDevMiddleware(complier, complier = webPack (webpackConfig) app.use(webpackDevMiddleware(complier, {/ / bind the common path of middleware, the same as the webpack configuration path publicPath: webpackConfig. Output. PublicPath, quiet:trueApp.use (express.static(DIST_DIR)) app.listen(PORT, PORT)function(){
    console.log("Successful startup: localhost:"+ PORT)
})
Copy the code

13. Output analysis

  • Profile: Records time-consuming information during the construction process.
  • Json: Outputs the build results in JSON format, culminating in a.json file that contains all build-related information.
webpack --profile --json > stats.json
Copy the code

Webpack Formally provides Webpack Analyse, a visual analysis tool

  • Modules: Shows all Modules, each module corresponds to a file. It also contains the dependency diagram, module path, module ID, Chunk of the module and module size of all modules.
  • Chunks: Shows all code blocks, including multiple modules in one code block. It also contains the code block ID, name, size, number of modules each code block contains, and a dependency diagram between code blocks;
  • Assets: displays all output file resources, including.js,.css, and images. It also includes the file name, size, and block of code from which the file came;
  • Warnings: Displays all Warnings that occur during the build.
  • Errors: Displays all error messages that occur during the build.
  • Hints: Shows how long it takes to process each module.

note

LibraryTarget and library

They are needed when using Webpack to build a library that can be imported and used by other modules.

  • Output.librarytarget configures how to export the library.
  • Output. library Specifies the name of the configuration export library. They are usually used together.

Output.librarytarget is an enumeration type of strings that supports the following configuration.

Var (default)

The libraries you write will be assigned via var to variables named by the library.

Library =’LibraryName’ if output.library=’LibraryName’ is configured, output and use the following code:

Var LibraryName = lib_code; // Use the library method libraryname.dosomething (); If output.library is empty, the output will be:Copy the code

Lib_code lib_code is a self-executing function that returns a value.

commonjs

The libraries written will be exported through the CommonJS specification.

Library =’LibraryName’ if output.library=’LibraryName’ is configured, output and use the following code:

// Webpack exports['LibraryName'] = lib_code; // Use the library's method require('library-name-in-npm') ['LibraryName'].doSomething(); Library-name-in-npm refers to the name of the module when it is published to the NPM repository.Copy the code

commonjs2

The written library will be exported via the CommonJS2 specification, with the following output and use code:

Module. exports = lib_code; // Webpack exports = module. // Use the library's method require('library-name-in-npm').doSomething(); CommonJS2 and CommonJS are very similar, except that CommonJS can only be exported from exports, while CommonJS2 adds module. Exports on the basis of CommonJS. When output.libraryTarget is commonjs2, configuring output.library makes no sense.Copy the code

this

The written library is assigned to the name specified by the library via this, and the output and use code is as follows:

// Webpack output code this['LibraryName'] = lib_code; Use the method of library / / this. LibraryName. DoSomething ();Copy the code

window

The written library will be assigned to the name specified by the library through the window, that is, the library will be mounted to the window, output and use the following code:

// Webpack output code window['LibraryName'] = lib_code; Use the method of library / / the window. The LibraryName. DoSomething ();Copy the code

global

// Webpack outputs the code global['LibraryName'] = lib_code; / / the method of using a library global. LibraryName. DoSomething ();Copy the code