Webpack 4.0: Javascript & split chunk

Time:2021-1-14

1、 Modular development of JS

javascriptThe reason why we need to package and merge is because of the existence of modular development. In the development phase, we need tojsThe files are written separately in many fragmentary files, which is convenient for debugging and modification. However, if you go online in this way, the first page will behttpThe number of requests will explode directly. For the same project, other people will get the required documents after 2-3 requests, while yours may need 20-30, so the results need not be mentioned.

But merge scripts are not“Copy all the fragmented files into one filejs“In the file”In this way, we can not only solve the problem of namespace conflicts, but also need to be compatible with different modular solutions, not to mention manually determining the loading order of modules according to the complex dependency relationship between modules. Therefore, we use automation tools to integrate the modules in the development phasejsIt is necessary to merge and optimize script fragments.

2、 General packaging requirements of JS files

  • Code compilation(TSorES6Code compilation)
  • Script merge
  • Common module identification
  • Code segmentation
  • Code compression confusion

3、 Using webpack to process JS file

3.1 using Babel to transform ES6 + syntax

babelyesES6Syntax conversion tool, rightbabelReaders who don’t know can read it firstBabel, the automation factory of big front end (3)We need to know more about it,babelAndwebpackThe combination method is also introduced here. Only the basic configuration is provided here

webpack.config.js:

...  
module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
             loader: 'babel-loader'
          }
        ]
      }
    ]
  },
 ...

.babelrc:

{
    "presets":[
        ["env",{
            "targets":{
                "browsers":"last 2 versions"
            }
        }
        ]],
    "plugins": [
         "babel-plugin-transform-runtime" 
    ]
}

3.2 script merging

usewebpackMerging scripts is very convenient, after allModule managementandFile mergeThese two functions arewebpackThe main purpose of the original design is not complicated until it comes to the topic of subcontracting and lazy loading.webpackIt’s very convenient to use because it implements the compatibility of different module specifications. For front-end developers, it’s better to understand the compatibility implementation than to learn how to configurewebpackMore important.webpackThe default support isCommonJsBut at the same time, in order to expand its use scenarios,webpackIn the subsequent version iteration, we also add theES harmonyAnd other specifications define the compatibility of the module, the specific processing method will be in the next chapterWebpack 4.0: moduleDetailed analysis.

3.3 common module identification

webpackYou can see the following parts in the output file of

/******/     function __webpack_require__(moduleId) {
/******/
/******/         // Check if module is in cache
/******/         if(installedModules[moduleId]) {
/******/             return installedModules[moduleId].exports;
/******/         }
/******/         // Create a new module (and put it into the cache)
/******/         var module = installedModules[moduleId] = {
/******/             i: moduleId,
/******/             l: false,
/******/             exports: {}
/******/         };
/******/
/******/         // Execute the module function
/******/         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/         // Flag the module as loaded
/******/         module.l = true;
/******/
/******/         // Return the exports of the module
/******/         return module.exports;
/******/     }

above__webpack_require__( )The way iswebpackModule loader, it is easy to see that there is a unified for the loaded moduleinstalledModulesObject to manage, so as to avoid the problem of repeated module loading. The common module also needs to start from thebundle.jsFile, which refers to the content of “code segmentation” in the next section.

3.4 code segmentation

Webpack 4.0: Javascript & split chunk

1. Why code segmentation?

The basic task of code segmentation is to separate the third-party dependency library. Because the content of the third-party dependency library may not change for a long time, it is used to mark the change summary hashcontentHashThis means that we can use the local cache to avoid unnecessary duplicate packaging, and use the browser cache to avoid redundant client loading. In addition, when the project releases a new version, if the third party relies oncontentHashNo change, you can use the client’s original cache file (the general practice is to set a large cache for static resource requests)max-age), improve access speed. In other scenarios, code segmentation can also provide the ability to control the loading time of the script in the whole loading cycle.

2. Use scenarios of code segmentation

Take a very common example, for example, you are doing a data visualization type website, which refers to BaiduEchartsAs a third-party library to render charts, if you put your own code andEchartsPackage them together to create amain.bundle.jsThe result is that when you open your website in an environment with poor network speed, users may have to face a long time of white screen, and you will soon think of the futureEchartsSeparate from the main file, let the smaller main file render some animation or prompt information on the interface, and then load itEchartsAnd separated outEchartsYou can also start from fasterCDNNode acquisition: if a huge library is loaded, you can also choose to use the lazy loading scheme to delay the script download time until the user actually uses the corresponding function. This is a kind of manual code segmentation.

From the whole life cycle of the above example, we split the script that can be loaded at one time into two times, which will undoubtedly increase the performance overhead of the server. After all, establishing a TCP connection is a very expensive operation, but it can be exchangedControl of rendering rhythm and improvement of user experienceAsynchronous moduleandLazy loading moduleFrom a macro point of view, they all belong toCode segmentationThe scope of the study.code splittingThe most extreme situation is actually to split it into its original appearance before packaging, that isSource code directly online

3. The nature of code segmentation
Webpack 4.0: Javascript & split chunk

The essence of code segmentation is to“Source code directly online”and“Package as a unique script main.bundle.js “Between these two extreme solutions, we need to find an intermediate state which is more in line with the actual situation, and exchange the acceptable server performance pressure for a better user experience.

4. Configure code segmentation

code-splittingThe configuration and usage of the technology will be described in detail in the next section.

5. More detailed code segmentation

Interested readers can refer to articles from Google developer community 《Reduce JavaScript Payloads with Code Splitting》 Self study.

3.5 code obfuscation compression

webpack4It’s built inUglifyJsPlug in, when packing mode parametersmodeSet toproductionIt’s not the only option, of course,babelThe plug-in can also provide code compression processing, the specific effect and principle of the author has not been studied, interested readers can study on their own.

4、 On split chunks Technology

4.1 parameter description

webpack4AbandonedCommonsChunkPluginPlug in, usingoptimization.splitChunksandoptimization.runtimeChunkInstead, the reason can be referred toWebpack 4: evolution in the ensembleOne article. aboutruntimeChunkParameters. Some articles say that the runtime part of the import and export chunk is extracted to form a separate file. Because this part does not change often, you can use the cache. The blog post of Google developer community is described as follows:

The runtimeChunk option is also specified to move webpack’s runtime into the vendors chunk to avoid duplication of it in our app code.

splitChunksThe default requirement for automatic code segmentation in is as follows:

  • node_ Modules in modules or other repeatedly referenced modules

    That is, if the referenced module comes fromnode_modulesAs long as it is referenced, it can be automatically segmented when other conditions are met. Otherwise, the module needs to be repeatedly referenced to judge other conditions. (corresponding to the configuration options belowminChunks1 or 2)

  • Minimum volume limit of module before separation (default 30K, modifiable)

    30K is the default value given by the government. It can be modified. As mentioned in the previous section, each subcontract corresponds to an increase in the performance cost of the server, so the cost performance of the subcontract must be considered.

  • For asynchronous modules, the number of generated common module files cannot exceed 5 (modifiable)

    When the download of lazy loading module is triggered, the number of concurrent requests should not exceed 5. For developers who have a little knowledge of server technology,[high concurrency]and[stress test]Such keywords should not be strange.

  • For the entry module, the number of public module files to extract cannot exceed 3 (modifiable)

    That is to say, the maximum number of parallel requests for an entry file cannot exceed 3 by default. The reason is the same as above.

4.2 parameter configuration

splitChunksYes, it iswebpackThe usage above 4.0 is as follows:

module.exports = {
  //...
  optimization: {
    splitChunks: {
      Chunks: 'async' // only works on asynchronous modules by default. When it is' all ', it works on all modules, and' initial 'works on synchronous modules
      Minsize: 30000, // volume of module file before merging
      Minchunks: 1, // minimum number of references
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      Automaticnamedelimiter: '~' // automatically name the connector
      cacheGroups: {
        vendors: {
          test: /[\/]node_modules[\/]/,
          minChunks:1 , // knock on the blackboard
          Priority: - 10 // higher priority
        },
        default: {
          test: /[\/]src[\/]js[\/]/
          Minchunks: 2, // it is generally a non third party public module
          priority: -20,
          reuseExistingChunk: true
        }
      },
      runtimeChunk:{
          name:'manifest'
      }
    }
  }

4.3 code segmentation examples

Note: the demo and configuration file used in the example have been attached.

  • Single page application

    A single page application has only one entry file,splitChunksThe main function of is to split the referenced third-party library. As can be seen from the following subcontracting results,node_modulesThird party references in are separated and placed in thevendors-main.[hash].jsIn the middle.

Webpack 4.0: Javascript & split chunk

  • Multi page application

    The situation of multi page application is a little more complicatedWebpack 4: evolution in the ensembleThe example in this article is code segmentation. The source code dependency is as follows:

    entryA.js: vue vuex component10k
    entryB.js: vue axios component10k
    entryC.js: vue vuex axios component10k
    

    The package after code segmentation is shown in the following figure:

Webpack 4.0: Javascript & split chunk

splitChunksIt provides a more accurate segmentation strategy, but it seems that it can not be directly passedhtml-webpack-pluginConfigure parameters to dynamically solve the problem of code injection after segmentation, because the subcontract name is uncertain. This scene is in usechunks:'async'The default configuration does not exist because the asynchronous module reference code does not need to be<script>Label injectionhtmlThe number of documents.

WhenchunksConfiguration item set toallorinitialFor example, in the above example, thehtml-webpack-pluginMedium configurationexcludeChunksCan be removedpageandaboutThese two chunks, however, cannot be excluded in advancevendors-about-pageThis is because it is impossible to know whether such a chunk will be generated before packaging. The author has not found a ready-made solution for this scenario. Readers who need this scenario may use ithtml-webpack-pluginOfEvent extensionTo deal with this kind of scenario, you can also use a compromise scheme, that is, after the first packaging, record the newly generated chunk name, and fill in thehtml-webpack-pluginOfchunksConfiguration item.

4.4 result analysis

adoptBundle BuddyAnalysis tools orwebpack-bundle-analyserThe plug-in can see the impact on the extraction of public code before and after subcontracting (the picture is from the blog post of the reference)

Webpack 4.0: Javascript & split chunk

5、 Reference and appendix description

【1】 Description of attached documents:

  • webpack.spa.config.js——Single page application code segmentation configuration example
  • main.js——Single page application entry file
  • webpack.multi.config.js——Multi page application code segmentation configuration example
  • entryA.js,entryB.js,entryC.js——Three entrances of multi page application

【2】 References:《Reduce JavaScript Payloads with Code Splitting》