Webpakc performance optimization
-
Development environment performance optimization
1. Optimize the packaging and construction speed
2. Optimize code debugging
-
Production environment performance optimization
1. Optimize the packaging and construction speed
2. Optimize the performance of your code
HMR: Hot modules replacement
- What it does: Changes to a module repackage only that module (not all of it), increasing build speed
-
Style files: You can use the HMR functionality because style-loader is implemented internally
-
Js file: HMR function cannot be used by default,
-
HTML files: the HMR function is disabled by default
To enable HMR, change entry to [‘./ SRC /index.js’,’./ SRC /index.html’]. HTML is a single file that is refreshed each time it is repackaged
-
devServer:{
contentBase:resolve(__dirname,'build'),
compress:true.port:3000.open:true
// Enable HMR
hot:true
}
Copy the code
/ / the new print. Js
/ / modify index. Js
if(module.hot){
// The HMR function must be enabled to execute this function
module.hot.accept('./print.js'.function(){
// Listen for changes to the print.js fileprint(); })}Copy the code
Source-map: a technique that provides source code to post-build code mapping
devtool:'eval-source-map'
Copy the code
Source-map: a technique that provides source-to-build code mapping (if the code goes wrong after the build, the mapping can trace the source code error)
Value: [the inline - | hidden - |eval-][nosources-][cheap-[module-]]source-map source-map: indicates the external link// Error code exact information and source code error location (down to column)Inline-source-map: inline, only one in-line source-map is generated// Error code exact information and source code error location (down to column)Hidden - source - the map: outreach// Error code exact information and error location of build code (only after build code)
eval-source-map: inline. Each file generates a corresponding source-map fileeval
// Error code exact information and source code error location (down to column)Nosources - source - the map: outreach// Error code exact information and no source code informationBeing the source - the map: outreach// Error code exact information and source code error location (down to line)
cheap-module- source - the map: outreach// Module will add loader source-map if there is no source-mapThe difference between inlining and inlining:1.External generated file, inline not;2.Faster inline build development environment: Faster, more debug friendly ----->eval-source-map/ eval-cheap-module- source - fast mapeval-cheap-source-map
eval-source-map debugging friendly source-map cheap-module-source-map cheap-source-map production environment: source code should not be hidden, debugging should not be more friendly ----->source-map/cheap-module-source-map
// Inlining will make the code larger, so it is not used in the reproduction environmentSource code should not be hidden nosource-source-map all hidden hidden-source-map only hide the source code, will be prompted after the build code error message debugging should not be more friendly source-mapCopy the code
Oneof, the following loader will only match one
// No two configurations can handle the same type of file
// There are two js matches here, and one js is levelled with oneof. Enforce takes precedence
module: {
rules: [{test: /\.js$/,
exclude: /node-modules/,
enforce: 'pre'.// priority syntax check
loader: 'eslint-loader'.options: {
fix: true}}, {oneof: [{test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'] {},test: /\.js$/,
exclude: /node-modules/,
loader: 'babel-loader'}]}]}Copy the code
4. Cache
1. Babel cache
Pros: Faster packaging the second time
cacheDirectory:true
2. File resource cache
Advantages: Better use of code running cache online
-
Hash: Webpack generates a unique hash value for each build
Problem: Js and CSS hash values are the same, repackaging will invalidate all caches (possibly changing a file)
-
Chunkhash: Hash value generated by chunk. If the package comes from the same chunk, the hash value is the same
Problem: JS and CSS still have the same hash value
-
Contenthash: Generates hash values based on file contents. Different files must have different hash values
/ / the Babel cache
{
test:/\.js$/
exclude:/node-modules/
loader:'babel-loader'
options: {parsets:[
[
'@babel/parset-env'
{
useBuiltIns:'usage'
corejs: {version:3},
targets: {chrome:'60'.firefox:'50'}}]],// Enable the Babel cache
// The second build reads the previous cache
cacheDirectory:true}}Copy the code
Tree shaking
Prerequisite: 1. Use ES6 modularization. 2. Must be in production mode. It is automatically enabled when the two conditions are met
What it does: Reduces code size and builds faster.
Configure in package.json
"sideEffects":falseNone of the code has tree shaking side effects. Problem: CSS / @babel/polyfill files might get dry"sideEffects": ["*.css"."*.less"]
Copy the code
B: Code split
// Production environment configuration
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
/ / a single entrance
//entry: './src/js/index.js',
/ / entrance
entry: {// There is an entry, and the final output has a bundle
index:'./src/js/index.js'.test:'./src/js/test.js'},output: {
//[name]: indicates the current file name
filename: 'js/[name].[contenthash:10].js'.path: resolve(__dirname, 'build')},plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'.minify: {
collapseInlineTagWhitespace: true.removeComments:true}})].mode: 'production'
}
Copy the code
// Production environment configuration
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
/ / entrance
entry: {index:'./src/js/index.js'.test:'./src/js/test.js'
},
// If 2 JS are introduced into JQ at the same time, the package generates 3 chunks
output: {
filename: 'js/[name].[contenthash:10].js'.path: resolve(__dirname, 'build')},plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'.minify: {
collapseInlineTagWhitespace: true.removeComments:true}})].//1. You can package the node-modules code separately into a chunk of final output
//2. Automatically analyze whether there are any common files in the multi-entry chunk. If there are any, they will be separately packaged into a chunk
optimization: {splitChunks: {chunks:'all'}},mode: 'production'
}
Copy the code
// Production environment configuration
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:'./src/js/index.js'
output: {
filename: 'js/[name].[contenthash:10].js'.path: resolve(__dirname, 'build')},plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'.minify: {
collapseInlineTagWhitespace: true.removeComments:true}})].// The code in Node-modules can be packaged separately into a chunk final output
optimization: {splitChunks: {chunks:'all'}},mode: 'production'
}
//index.js
/* The file is packaged separately into a chunk */ with js code
/*webpackChunkName:'test'*/Set file name imoprt (/*webpackChunkName:'test'*/'./test').then(({mul,count}) = >{
// The file was successfully loaded
console.log(mul(2.3))
}).catch(() = >{
// Failed to load file
})
Copy the code
B: Lazy loading
// Lazy loading: files are loaded only when they are needed
// Preload prefetch: will be used before preloading the JS file webpackPrefetch:true
// Normal loading: parallel loading (multiple files are loaded at the same time)
imoprt(/* webpackChunkName:'test',webpackPrefetch:true*/ './test').then(({mul}) = >{
console.log(mul(2.3))})Copy the code
PWA: Progressive Web Application Development Program (Offline access)
// Production environment configuration
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const workboxWebpackPlugin = require('workbox-webpack-plugin')
// Specify node environment variables
//process.env.NODE_ENV = 'development'
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// Browserslist also needs to be configured in package.json
/* "browserslist": { "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ], "production": [">0.2 ", "no dead", "no op_mini all"]}, */
loader: 'postcss-loader'.options: {
ident: 'postcss'.plugins: () = > [
require('postcss-preset-env')()]}}]module.exports = {
entry: './src/index.js'.output: {
filename: 'js/[name].[contenthash:10].js'.path: resolve(__dirname, 'build')},module: {
rules: [{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'] {},// eslintConfig needs to be configured in package.json --> Airbnb
/* "eslintConfig": { "extends": "airbnb-base", "env":{ "browser":true } } */
test: /\.js$/,
exclude: /node-modules/,
enforce: 'pre'.// priority syntax check
loader: 'eslint-loader'.options: {
fix: true}}, {test: /\.js$/,
exclude: /node-modules/,
loader: 'babel-loader'.// Convert a higher version of JS to ES5
options: {
presets: [['@babel-loader',
{
useBuiltIns: 'usage'.corejs: {
version: 3
},
targets: {
chrome: '60'.firefox: '50'}}]]}}, {test: /\.(jpg|png|gif)$/,
loader: 'url-loader'.options: {
limit: 8 * 1024.esModule: false.name: '[hash:10],[ext]'.outputPath: 'images'}}, {test: /\.html$/,
loader: 'html-loader'
},
{
exclude: /\.(css|less|html|js|jpg|png|gif)$/,
loader: 'file-loader'.options: {
name: '[hash:10],[ext]'.outputPath: 'media'}}},plugins: [
new MiniCssExtractPlugin({
filename: 'css/bulit.css'
}),
new optimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html'.minify: {
collapseInlineTagWhitespace: true.removeComments:true}}),new workboxWebpackPlugin.GenerateSW({
/** * 1. Help serviceWorker start quickly * 2. Delete old serviceWorker * * Generate a serviceWorker file */
clientClaim:true.skipWaiting:true})].mode: 'production'.devtool:'source-map'
}
Copy the code
//index.js
/** * 1. EslintConfig * "evn":{* "browser":true *} * 2 in package.json Must run */ on the server
// Register the serviceWorker in the entry file
// Handle compatibility issues
if('serviceWorker' in navigator){
window.addEventListente('load'.() = >{
navigator.serviceWorker.register('/service-worker.js').then(() = >{
console.log('serviceWorker registered successfully ')
}).catch(() = >{
console.log('serviceWorker registration failed ')})})}Copy the code
Nine, multi-process packaging
//thread-loader enables multi-process packaging, which takes about 600ms. The multi-process packaging is enabled only when the work takes a long time
//npm install thread-loader -D
{
test:/\.js$/
exclude:/node-modules/,
use:[
{
// Enable multi-process packaging
loader:'thread-loader'.options: {workers:2.// Start two processes}}, {loader:'babel-loader'.options: {presets: [['@babel-loader',
{
useBuiltIns: 'usage'.corejs: {
version: 3
},
targets: {
chrome: '60'.firefox: '50'}}]]}}Copy the code
Externals prevents certain packages from being exported to the bundle and imported directly through the CDN
const { resolve } = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./js/index.js'.output: {filename:'./js/[name].[contenthash:10].js'.path:resolve(__dirname,'build')},plugins: [new htmlWebpackPlugin({
template:'./src/index.html'.minfy: {collapseInlineTagWhitespace: true.removeComments:true}})].mode:'production'.externals: {// Refuse to package jquery
jquery:'jQuery'}}Copy the code
Eleven, DLL, the third party library separately packaged, directly introduced
//webpack.dll.js
/* Use DLL technology for third-party libraries (jQuery, vue, react...) Pack separately */
const {resolve} = require('path')
const webpack = require('webpack')
module.export = {
entry: {// Package to generate the name, to package the library
jquery: ['jquery']},output: {filename:'[name].js'.path:resolve(__dirname,'dll'),library:'[name]_[hash:10]'// Package the library to expose the content name
},
plugins: [// Package to generate a manifest.json file to provide jQuery mapping
new webpack.DllPlugin({
name:'[name]_[hash:10]'.// Map the library to the exposed namePath: resolve (__dirname,'dll/manifest.json')// Output file directory})].mode:'production'
}
Copy the code
//webpack.config.js
const { resolve } = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports={
entry:'./src/index.js'.output: {filename:'js/[name].[contenthash:10].js'.path:resolve(__dirname,'build')},plugins: [new htmlWebpackPlugin({
template:'./src/index.html'.minfy: {collapseInlineTagWhitespace: true.removeComments:true}}),// Tell Webpack that libraries are not packaged and that their names change when used
new webpack.DllReferencePlugin({
manifest:resolve(__dirname,'dll/manifest.json')}),// Package third-party libraries separately and import them automatically in HTML
new AddAssetHtmlWebpackPlugin({
filepath:resolve(__dirname,'dll/jquery.js')})],mode:'production'
}
Copy the code
Summary of Performance Optimization
1. Webpack performance optimization
- Development environment performance optimization
- Production environment performance optimization
Second, development environment performance optimization
- Optimize packaging build speed
- HRM
- Optimized code debugging
- source-map
- Development environment: eval – source – the map | | eval – being – the module – the source – the map
- Production: the source – the map | | being – the module – the source – the map
- source-map
Optimization of production environment performance
- Optimize packaging build speed
- oneOf
- Babel cache
- Multi-process packaging
- Externals,
- dll
- Optimize code performance
- Cache (hash | | chunkhash | | contenthash)
- Thee shaking (1, Using ES6 modularity. 2, must be in
production
Mode. It is automatically turned on if the two conditions are met.) - code split
- lazy loading
- pwa