Mainly packaging optimization

ignorePlugin

When you do not need all the functionality of a package, you can ignore some files and manually introduce the corresponding functionality installation

NPM install moment; // Install moment; // Install momentCopy the code
// index.js
import moment from 'moment'
moment.locale('zh-cn')

var r = moment().endOf('day').fromNow();
console.log(r)
Copy the code

The whole index.js file is 500+ KB. The previous package was only 50+ KB, mainly because all the files in moment/locale are large

But I want to import only Chinese files, can not import all files in the package

configuration

// webpack.config.js let webpack = require('webpack') module.exports = { plugins: [ new webpack.ignorePlugin(/\.\/locale/, /moment/)]} // index.js import moment from 'moment' // import 'moment/locale/zh-cn' moment.locale('zh-cn') var r = moment().endOf('day').fromNow(); console.log(r)Copy the code

dllPlugin

Dynamically linked libraries can package some large libraries separately and introduce them separately with script, so that these large libraries with little change do not need to be repackaged or compiled at compile time

For example, react

npm install react react-dom
Copy the code
// index.js import React from 'React' import {render} from 'React -dom' render(<h1> React </h1>, window.root)Copy the code

New webpack. React. Congfig js, separate pack to react

Webpack.dllplugin generates a mapping file that is associated with the webpack.congfig. Js DllReferencePlugin, so that when index.js is introduced into React, it will find manifest.json first and not pack it

// webpack.react.congfig.js let path = require('path') let webpack = require('webpack') module.exports = { mode: 'development', entry: {react: ['react', 'react-dom'] // Third party to package}, output: {filename: Resolve (__dirname, 'dist'), library: // libraryTarget: 'var' // umd var this commonjs}, '_dll_[name]', // will take on the value returned by (function(modules) {return XXX}) [// Generate a mapping file associated with the webpack.congfig. Js DllReferencePlugin so that when index.js is introduced into React, New webpack.DllPlugin({// name == library name: '_dll_[name]', path: {// name == library name: '_dll_[name]', path: path.resolve(__dirname, 'dist', 'manifest.json') }) ] }Copy the code

After the configuration is complete, execute

npx webpack --config webpack.react.config.js
Copy the code

After packaging, can generate _dll_react. Js and manifest. Json, that how to make the main engineering package, can use the _dll_react. Js, not wrap up the react to the index. The js insideConfiguration webpack. Config. Js. New webpack DllReferencePlugin, with webpack. DllPlugin formation correlation

// webpack.config.js module.exports = {mode: "production", // SRC /index.js' entry: {index: './ SRC /index.js',}, devServer: {open: true, contentBase: './dist', output: {filename: Resolve (__dirname, 'dist')}, plugins: [ ... new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, 'dist', 'manifest.json') }), ], module: { rules: [ { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: [ '@babel/preset-env', '@babel/preset-react' ] } } } ] } }Copy the code

Repackage the main project and you’ll notice that index.js is small and doesn’t pack all react

Finally, manually import the packaged _dll_react.js in index.html

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document给对方</title>
</head>
<body>
    <div id="root"></div>
    <script src="/_dll_react.js"></script>
</body>
</html>
Copy the code

Run the main project

happypack

Can achieve multi-threaded packaging, is a third party package

npm install happypack
Copy the code

Happypack uses the configuration previously written for use in rules

// webpack.config.js const Happypack = require('happypack') module.exports = { ... plugins: [ // css new Happypack({ id: 'css', use: ['style-loader', 'css-loader'] }) // js new Happypack({ id: 'js', use:[ { loader: 'babel-loader', options: { presets: [ '@babel/preset-env', '@babel/preset-react' ] } } ] }), ], module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: 'Happypack/loader? Id =js', {test: /\. CSS $/, use: 'Happypack/loader? Id = CSS '}]}Copy the code

Packaging, you will see that there are 3 processes for packaging, but the allocation process also consumes performance, so it is recommended for large projects to use this method, otherwise the packaging is slow

noParse

Do not resolve a library’s dependent libraries

module.exports = {
    ...
    module: {
        noParse: /jquery/
    }
}
Copy the code

Webpack comes with optimizations

1) Import automatically removes useless code in production environment

The alias tree – shaking

For example, a package exports multiple methods, but only one of them is used in the actual project. When the packaging mode is production, it does not package useless methods

2) If require is used, it does not remove useless code and puts the exported result into default

let calc = require('./test')
console.log(calc.default.sum(1, 2))
Copy the code

3) Scope Hosting scope upgrade

Some code that can be simplified is automatically omitted in Webpack

Pull out the common code

Multi-entry project, extract common code into a module file ready to add common.js

function sum(a, b) {
    return a + b
}

export default sum
Copy the code

Other.js /index.js import this module

import sum from './common'
console.log(sum(3, 5))
Copy the code

Configure multi-entry packaging, when packaging, you will find that the common code is packaged into their own files, the whole project is redundant

Can we, uh, isolate the common code into separate files

configuration

Module.exports = {mode: "development", optimization: {splitChunks: {// cacheGroups: {common: {chunks: { 'initial', // start minSize: 0, // start minChunks: 2, // start minChunks: 2, // start minChunks: 2Copy the code

Once you’ve packaged it, you’ll find an additional common Index Other.js with the common sum module.

However, if I reference third-party libraries, such as jquery and Boostrap, can I separate these libraries into another library? If they are not configured, they will also be packaged by defaultcommon~index~other.js

The third-party library package configuration other.js/index.js imports this module

import sum from './common'
console.log(sum(3, 5))

import $ from 'jquery'
console.log($)
Copy the code
Module.exports = {mode: "development", optimization: {splitChunks: {// cacheGroups: {common: {chunks: { 'initial', // start with minSize: 0, // start with minChunks: 2, // start with minChunks: 2}, vendor: {priority: 1, / / weight, first out of a third party, and then go out of the common public code block, or will be in all common test:, / node_modules/chunks: 'initial', / / entrance minSize: 0, // how old is minChunks: 2? // how old is minChunks: 2? // how old is minChunks: 2?Copy the code

Lazy loading

You can control the loading of resources at one point, rather than initially loading all files ready to create source.js

export default 'ZDFJ'
Copy the code

Index.js, click to load source.js

Let button = document.createElement('button') button.adDeventListener ('click', function() { Import ('./source.js').then(function(data){console.log(data)})}) document.body.append(button) import('./source.js').then(function(data){console.log(data)})}) document.body.append(button)Copy the code

Drop the service, click the button, and you’ll see that 0.js is loaded, and this file will be generated when packaged

Hot update

Instead of refreshing the page, update the code

Documents to prepare

Import STR from './source' if(module.hot) {module.hot.accept('./source', ()=>{console.log(' file updated ')})}Copy the code

configuration

module.exports = { ... devServer: { ... Hot: true // Start hot updates}, plugins: [... new webpack HotModuleReplacementPlugin (), / / hot update plug-in new webpack. NamedModulesPlugin (), / / print hot update path]}Copy the code

Change the source code and you will see that the page is not refreshed