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