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

  1. 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)

  2. 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

  3. 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
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 inproductionMode. It is automatically turned on if the two conditions are met.)
    • code split
    • lazy loading
    • pwa