• Webpack 4.X Combat (1) : Have a comprehensive understanding of Webpack and core concepts

  • Build a simple front-end project from scratch

  • Webpack4.x Actual combat (3) : 24 points summary of enterprise SPA (1)

  • Webpack4.x actual combat (IV) : 24 points summary of enterprise SPA (ii)

    Outline of this article: project packaging configuration, optimization

13. Configure the package output path

  • There are three common configurations for webpack configuration file output paths

    • Configuration 1: Exit Entry. Path: Sets the output paths of all files

      // webpack configuration const path = require('path');
      const rootPath = path.resolve(__dirname, ' ');
      
      
      module.exports = {
          output: {
              path: path.resolve(rootPath, './dist'// All resources will be output to the dist folder in the root directory of the projectCopy the code
    • Configuration 2: options.outputPath of loader: configures the outputPath that the current loader matches to the file

      The file output for this configuration is based on the entry. Path path

      Module. exports = {output: {path: path.resolve(rootPath,'./dist')
          },
                 
          module: {
              rules: [{
                  test: /\.(png|jpg|gif|ico)$/,
                  use: [{
                      loader: 'url-loader',
                      options: {
                          limit: 8192,
                          name: '[name].[ext]',
                          outputPath: 'static/assets/'}}]}}; Dist /static/assets folder in the root directory of the projectCopy the code
    • Configuration 3: The value of the name option, which can change the output path of the current package

      Export entry.chunkfilename and change the output location of all chunk packets (except runtimeChunk)

      Module. exports = {output: {path: path.resolve(rootPath,'./dist'),
              chunkFilename: 'static/js/[name].js'}}; Dist /static/js folderCopy the code

      Optimization.splitchunks name value, using the output.chunkfilename path as the standard

      Module. exports = {output: {path: path.resolve(rootPath,'./dist'),
              chunkFilename: 'static/js/[name].js'
          },
                 
          optimization: {
              splitChunks: {
                  cacheGroups: {
                      libs: {
                          test: /[\\/]node_modules[\\/]/,
                          priority: 20,
                          name: '.. /libs/index',
                          chunks: 'all'}}}}}; // Put splitChunks in dist/static/js folderCopy the code

      [special] optimization. RuntimeChunk name value, to the output. The path path as the standard

      Module. exports = {output: {path: path.resolve(rootPath,'./dist'),
              chunkFilename: 'static/js/[name].js'
          },
         
          optimization: {
              runtimeChunk: {
                  name: 'static/runtime/index'}}}; Dist /static/ Runtime; dist/static/runtimeCopy the code

14. Configure static resource publishing path (convenient for CDN to request resources)

  • Function: configure the release path, let the page request CDN static resources, faster

  • Configure the publicPath: output.publicPath

    Exports = {output: {publicPath:'http://aaa.com/'}};Copy the code
  • Configure static resources separately: Loader options

    module.exports = {
        module: {
            rules: [{
                test: /\.(png|jpg|gif|ico)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 8192,
                        name: '[name].[hash:8].[ext]',
                        outputPath: 'static/assets/',
                        publicPath: 'http://aaa.com/assets/'}}]}};Copy the code

15. Configure hash for the cache of packaged files

  • Default naming rules for webPack modules:

    • Webpack defaults to assigning an ID to each module as its name

      The default ID is an integer (0, 1, 2, 3…), depending on the order in which the module was introduced.

      The default ID is used to handle dependencies between modules

    • Cache files by configuring different hashes

  • Webpack comes with a variety of hashes to work with, as explained below:

    • hash: the hash of the module identifier

    • chunkHash: the hash of the chunk content

    • contentHash: the hash of extracted content

  • Sets the length of the hash

    // Global SettingshashThe length of the output. HashDigestLengthCopy the code
    // Local SettingshashThe length of the [hash: 16], etcCopy the code
  • Configure when to generate the hash

    // output.hashDigest
    Copy the code
  • How to choose the right onehash

    • JS, detached CSS, and resource files (images, font ICONS) all use hash

      • The hash value of the CSS file is the same each time the JS is packed and the CSS file is separated

      • The project code remains unchanged and is packaged again; All file hashes remain unchanged

      • As long as JS and CSS have one change, all JS and CSS file hashes change

      • The resource file (image, font icon) is not updated, the hash value is unchanged; Hash is a good option

    • JS, detached CSS, resource files (images, font ICONS) all use chunkHash

      • Package the JS of the same page each time, and separate the CSS hash value is the same; The hash values of THE JS and CSS files vary from page to page

      • The project code remains unchanged and is packaged again; All file hashes remain unchanged

      • The project code has changed, only has changed JS, the corresponding CSS file hash value change; The other file hashes remain the same

      • Resource files (images, font ICONS) cannot use chunkHash, an error is reported

    • Best practices:

      • [name].[chunkHash:8].js

      • Separated CSS file: [name].[contentHash:8].css

        Does not change the hash as JS changes

      • Resource file (image, font icon) : [name].[hash:8].[ext]

16. Automatically clean the clean-webpack-plugin file before packaging

  • Use the clean-webpack-plugin to empty the last packed file before packaging

    If you do not clear the file, the size of the packed file will become larger and larger

  • The installation

    NPM [email protected] - I DCopy the code
  • configuration

    For details, see

    // Webpack const CleanWebpackPlugin = require('clean-webpack-plugin');
    
    module.exports = {
        plugins: [
            new CleanWebpackPlugin(['dist']) // The value is the empty folder in the root directory]}Copy the code

17. Simplify packaging according to search rules

  • Webpack provides a built-in plug-in: ContextReplacementPlugin

    The official configuration

    // Just pack the moment... plugins: [ new webpack.ContextReplacementPlugin( /moment[/\\]locale$/, /zh-cn/, ), ] ...Copy the code

18. Code splitting during packaging

  • New and old API updates

    • Webpack3 use plug-ins optimize.Com monsChunkPlugin to split the code

    • Webpack4 remove plug-ins, the new optimization splitChunks, optimization, runtimeChunk to segment the code

      The biggest feature of Code Splitting in Webpack 4 is the simplicity of configuration (starting with 0 configuration) and automatic Splitting based on built-in rules

  • Why split code?

    • Compilation: Reduce the overall size of compilation to improve build performance

    • Operation: reduce file size, improve loading speed

      This is relative; while code splitting reduces file size, a reasonable number of HTTP requests should also be considered

  • What code is usually split?

    • Extract public code

    • Extract common library code

    • Extract the WebPack Runtime code

  • The default split code mechanism of Webpack4, which meets the following conditions, is split by default

    • The new bundle is referenced by two or more modules, or from node_modules

    • New bundle larger than 30KB (before compression)

    • Asynchronous loading A maximum of five bundles can be concurrently loaded

    • The number of bundles initially loaded cannot be greater than 3

  • The default configuration is as follows:

    See the official website for detailed configuration

    Module.exports = {// exports = {//... optimization: { splitChunks: { chunks:'async'MinSize: 30000, minSize: 0, minChunks: MaxAsyncRequests: 3, maxInitialRequests: 3, automaticNameDelimiter:'~'// Automatically name the concatenator name:true,
                cacheGroups: {
                    vendors: {
                        test: /[\\/]node_modules[\\/]/, priority: -10 // For those with higher priority}, default: {minChunks: 2, priority: -20, reuseExistingChunk:true}}}}};Copy the code
  • Custom code optimization segmentation. SplitChunks. CacheGroups

    Optimization. SplitChunks. CacheGroups under each chunk of configuration options with optimization. The splitChunks configuration options

    If set, the configuration option under Optimization.splitchunks will be overridden; Inherit if not set

    Module.exports = {optimization: {splitChunks: {cacheGroups: {libs: {test: /[\\/]node_modules[\\/]/,
                        priority: 20,
                        name: '.. /libs/index',
                        chunks: 'all'}}}}};Copy the code
  • Package the WebPack Runtime code separately

    Module.exports = {optimization: {runtimeChunk: {name:'static/runtime/index'}}};Copy the code
  • In special scenarios, manual code segmentation is required. Please refer to the following cases

    • Webpack 4 configuration best practices

    • webpack – SplitChunksPlugin

    • webpack 4: Code Splitting, chunk graph and the splitChunks optimization

19. Multi-threaded packaging with HappyPack (speed up compilation)

  • By default, WebPack processes tasks single-threaded

    Since Webpack running on Node.js is a single-threaded model

    So the things that Webpack needs to deal with need to be done one by one, not all at once

  • HappyPack lets WebPack handle multiple tasks at once

    It divides the task into several sub-processes for concurrent execution, and then sends the result to the main process after the sub-process finishes processing

    Thus reducing the total build time and improving the build efficiency

  • HappyPack processes JS and is configured as follows

    // Install NPM I [email protected] -dCopy the code
    // webpack configuration as follows const OS = require('os');
    const HappyPack = require('happypack');
    const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
    
    
    module.exports = {
        module: {
            rules: [{
                test: / \. Js $/, / / to. Js file processing to id for happyBabel HappyPack instance execution loader:'happypack/loader? id=happyBabel'
            }]
        },
        plugins: [
            new HappyPack({
                id: 'happyBabel'Loaders: [{loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders: {loaders:'babel-loader? cacheDirectory=true'}], threadPool: happyThreadPool, // share process pool verbose:true// Allow HappyPack to print logs})]};Copy the code
  • Illustrate the module. Rules. Loader

    • In Loader configuration, all files are handled by happypack/ Loader

    • Use the ones that follow? Id =happyBabel tells happypack/loader to select which instance of Happypack to process files

  • HappyPack parameter

    • Id: String Uses a unique identifier ID to indicate that the current HappyPack is used to process a particular class of files

    • Loaders: Array is used the same as in the WebPack Loader configuration

    • Threads: Number indicates the Number of child processes to handle this type of file. The default Number is 3. The type must be an integer

    • Verbose: Boolean Specifies whether HappyPack is allowed to output logs. The default value is true

    • ThreadPool: HappyThreadPool represents a shared process pool (that is, multiple Instances of HappyPack use child processes in the same shared process pool to handle tasks to prevent excessive resource usage)

    • VerboseWhenProfiling: Boolean Opens Webpack –profile and still expects HappyPack to produce output

    • Debug: Boolean Enables debug for troubleshooting. The default false

  • Note:

    • HappyPack creates a separate postcss.config.js file to handle CSS/SCSS. Otherwise, an error will be reported

    • HappyPack has limited support for url-loader and file-loader

  • In doubt

    • Problem: The project is only configured with child threads to compile JS, but the compilation is slower (the project does not separate CSS; Project code is not much, production environment packaged volume 1.13m)

    • HappyPack multithreading starts the child thread processing first, and then passes the result to the main thread. This takes longer than the time saved by multithreading packaging (because there are not many JS to compile).

20. DLL Dynamic link library (improve compilation speed)

  • Know the DLL

    Can contain functions and data called to other modules

    Anyone who has used Windows will often see files with the.dll suffix

  • To build an access dynamic link library for a Web project, do the following:

    • Separate the base modules that web pages depend on and package them into separate dynamic link libraries (a dynamic link library can contain multiple modules)

    • When a module to be imported exists in a dynamically linked library, the module cannot be packaged again, but is retrieved from the dynamically linked library

    • All dynamic link libraries that the page depends on need to be loaded

  • Web projects build access dynamic link libraries, benefits: improved build speed (no need to repackage each build)

  • Webpack already has built-in support for dynamically linked libraries

    • DllPlugin: Package out individual dynamic link library files

    • DllReferencePlugin: Introduce the DllPlugin plugin packaged dynamic link library file in the main configuration file

  • Practice the DLL

    // webpack/dll.config.js const path = require("path");
    const webpack = require("webpack");
    const libs = require('.. /configs/dll.config');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    
    
    
    module.exports = {
        mode: 'production', entry: {// Put the vUE related modules into a separate dynamic link library vue: ['vue'.'vue-router'], // Put all the lib needed for the project into a single dynamically linked library lib: ['jquery'.'moment'],
        },
    
        output: {
            path: path.resolve(__dirname, './dll'),
            filename: "[name].js",
            library: "_dll_[name]"
        },
    
        plugins: [
            new webpack.DllPlugin({
                name: "_dll_[name]",
                path: path.join(__dirname, 'dll'.'manifest.json'}), // Clean up the DLL folder new CleanWebpackPlugin(['dll'])]}Copy the code
    Configure NPM script {"scripts": {
            "dll": "webpack --config webpack/dll.config.js",}}Copy the code
    Install dependency package NPM I [email protected] -dCopy the code
    // webpack configuration file const webpack = require('webpack'); Module. Exports = {plugins: [/ / enable DLL new webpack DllReferencePlugin ({context: __dirname, manifest: require ('./dll/manifest.json')]}});Copy the code
    // New dowload down the project, need to first DLL package, then run the projectCopy the code

21. Introduce third-party libraries globally

  • Webpack built-in plug-ins that support global introduction of third-party libraries

    // const webpack = require('webpack');
    
    plugins:[
        new webpack.ProvidePlugin({
            $:"jquery"})].Copy the code
  • Contrast:

    • Global introduction:

      After global introduction, the project code can be used directly

      Third-party libraries will not be packaged if there is nowhere else to use them

    • Local introduction:

      Import each file individually if necessary

      Once introduced, third-party libraries will be packaged even if they don’t work

Visual analysis of packaging volume

  • Plug-in: webpack – bundle – analyzer

    • The effect

    • There are three sizes in the generated report:

      • Stat: Input file size before compression, etc. (obtained from the stat object in Webpack

      • Parsed: size of webpack output JS files (excluding resource files, separated CSS, etc.)

      • Gzip: gzip compressed size

    • use

      // Install NPM I [email protected] -dCopy the code
      // webpack configuration const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] }; // The analysis results are automatically displayed in the browser after the packaging is completeCopy the code
  • Plug-in: webpack – chart

    • Online analysis address

  • Plug-in: webpack – analyse

    • Online analysis address

23. Simplify terminal output

  • Deployment packaging configuration

    Module.exports = {// webpack configuration file module.exports = {//false,
            children: false,
            chunks: false,
            chunkModules: false}};Copy the code
  • Run the configuration webpack-dev-server locally

    Module.exports = {devServer: {// stats: {modules:false,
                children: false,
                chunks: false,
                chunkModules: false}}};Copy the code
  • See Webpack State for details

24. Display packaging progress

  • The following plug-ins can display the packaging progress. For details, refer to GitHub

    • progress-bar-webpack-plugin

    • nyan-progress-webpack-plugin

    • progress-bar-webpack-plugin

    • progress-webpack-plugin