webpack
As the most fire-front building tool, is the most important part of the front-end automation tool chain, the use of high threshold. This series is the author's own study record, compares the foundation, hoped through the problem + solves the pattern, takes the front-end construction to meet the concrete demand as the starting point, the Learning webpack
tool corresponding processing method. (The parameter configuration and usage methods in this article are based on webpack4.0版本
)
This article summarizes:
This article mainly introduces webpack4.0
the splitChunks
sub-package technology based on.
[TOC]
A. JS Modular development
javascript
The need for package consolidation is due to the existence of modular development. Development phase we need to js
separate files in a number of fragmented files, easy to debug and modify, but if it is so online, the first page of the http
number of requests will be directly exploded. The same project, others 2-3 requests to get the required files, and you may need 20-30, the result will not have to say more.
But the merge script does not "copy all of the fragmented files into a js
file" so that you can solve not only the problem of namespace collisions, but also the compatibility of different modular schemes, not to mention that the module's loading order is manually determined based on the complex dependencies between the modules. Therefore, it is necessary to use automation tools to js
combine and optimize script fragments in the development phase.
Two. js file for general packaging requirements
- Code compilation (
TS
or ES6
compilation of code)
- Script Merge
- Public module identification
- Code segmentation
- Code compression obfuscation
Three. Using Webpack to process JS files 3.1 using Babel conversion es6+ syntax
babel
is a ES6
grammar conversion tool, for those babel
who do not understand can read the "Large front end of the Automation factory (3)--babel" article to understand, babel
and the webpack
use of the method is also described in it, here only the basic configuration:
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 Merge
It is very convenient to use a webpack
combination of scripts, after all, the two functions of module Management and file merging are the webpack
primary purpose of the original design, and only become complex when it comes to the topic of subcontracting and lazy loading. webpack
easy to use because of the compatibility of various module specifications, it is more important for front-end developers to understand how this compatibility is implemented than to learn how to configure it webpack
. webpack
the specification is supported by default CommonJs
, but in order to extend its usage scenarios, the webpack
compatibility of other specification modules is added to the subsequent version iterations ES harmony
, which will be handled in the next chapter, webpack4.0 Conquer (5)-- Module Chapter detailed analysis.
3.3 Public Module identification
webpack
You can see the following sections in the output file:
/******/function __webpack_require__ (moduleid) {/******//******///Check if mod Ule is in cache/******/if (Installedmodules[moduleid]) {/******/return Installedmodules[moduleid].expor ts;/******/}/******///Create a new module (and put it into the cache)/******/var module = Install Edmodules[moduleid] = {/******/i:moduleid,/******/l:false,/******/exports: {}/****** /};/******//******///Execute the module function/******/modules[moduleid].call (Module.exports, MO Dule, Module.exports, __webpack_require__)/******//******///Flag the module as loaded/******/MODULE.L = true;/******//******///Return the exports of the module/******/return module.exports;/******/}
The above __webpack_require__( )
method is webpack
the module loader, it is easy to see that the loaded modules have a unified installedModules
object to manage, thus avoiding the problem of the module repeated loading. Common modules also need to be extracted from the bundle.js
file, which involves the "code splitting" of the next section.
3.4 Code Splitting
1. Why do you want to split the code?
The most basic task of code splitting is to isolate third-party dependent libraries, because the contents of a third-party library may not change for a long time, so the digest hash used to mark the change is contentHash
long-lasting, which means we can use the local cache to avoid unnecessary duplication of packaging. and use the browser cache to avoid redundant client loading. In addition, when a new version of the project is released, if the third party depends on the contentHash
changes, the client can use the original cache file (general practice is to set a large static resource request max-age
), improve access speed. In other scenarios, code splitting can also provide the ability to control the load time of the script throughout the load cycle.
2. Usage scenarios for code splitting
A very common example, such as you are doing a data visualization type of Web site, referring to Baidu Echarts
as a third-party library to render the chart, if you put your own code and Echarts
packaged together to generate a main.bundle.js
file, the result is to open your site in an environment with poor speed, Users may need to face a long time white screen, you will soon think of the Echarts
main file will be stripped out, so that the smaller main file in the interface to render some animation or information, and then to load Echarts
, and the separation Echarts
can also be obtained from a faster CDN
node, If you load a large library, you can also choose to use lazy loading scenarios to defer the download time of the script until the user actually uses the corresponding feature. This is a manual code segmentation.
From the entire life cycle of the above example, we split the script that could have been loaded once for two times, which will undoubtedly aggravate the performance overhead of the server, after all, establishing a TCP connection is a costly operation, but it can be used to improve the control of the rendering rhythm and the user experience. The asynchronous module and the lazy loading module are actually all in the category of Code Division in the macroscopic aspect. The code splitting
most extreme situation is actually split into the original before packaging, that is, the source code directly online .
3. The nature of code segmentation
The essence of code segmentation is to find a more realistic intermediate state between the two extreme scenarios of "source direct online" and "packaged as a unique script main.bundle.js" . In exchange for a better user experience with an increase in acceptable server performance pressures.
4. Configure code splitting
code-splitting
The configuration and usage of the technology are described in detail in the next section.
5. More Granular Code Segmentation
Interested readers can refer to the article "Reduce JavaScript payloads with code splitting" from the Google developer community for their own research.
3.5 Code Obfuscation compression
webpack4
Has built-in UglifyJs
plug-in, when the packaging mode parameters are mode
set to production
automatically open, of course, this is not the only choice, babel
the plug-in can also provide code compression processing, the specific effects and principles of the author has not yet, interested readers can self-study.
Four. Detail Splitchunks Technology 4.1 parameter description
webpack4
Abandoned CommonsChunkPlugin
plug-ins, use optimization.splitChunks
and optimization.runtimeChunk
to replace, the reason can refer to the "Webpack4: The Evolution of Legato" article. With regard runtimeChunk
to parameters, some articles say that the runtime part of the chunk is extracted from the entrance and exit, forming a separate file, because this part does not change frequently, can use the cache. This is described in the Google Developer Community blog post:
? The? runtimeChunk
? Option?is also specified to Move?webpack ' s Runtime?into the? vendors
? Chunk to avoid duplication of the it in our app code.
splitChunks
The default code auto-segmentation requirements are as follows:
Modules in Node_modules or other modules that are repeatedly referenced
That is, if the referenced module is from node_modules
, then as long as it is referenced, then the other conditions can be automatically split. Otherwise, the module needs to be repeatedly referenced to continue judging other conditions. (corresponds minChunks
to a scenario of 1 or 2 in the configuration options below)
Minimum volume limit of the module before separation (default 30k, modifiable)
30k is the default value given by the official, it can be modified, as already mentioned in the previous section, each sub-package corresponds to the service side of the performance cost increase, it is necessary to consider the cost-effective sub-package.
For asynchronous modules, the generated public module files cannot exceed 5 (modifiable)
When the lazy load module is triggered to download, the concurrent request can not exceed 5, for a little understanding of the service-side technology developers,"high concurrency" and "stress test" Such keywords should not be unfamiliar.
For ingress modules, the public module files drawn out cannot exceed 3 (modifiable)
This means that the maximum concurrent request for a portal file must not exceed 3 by default for the same reason.
4.2 Parameter Configuration
splitChunks
The webpack
usage in version 4.0 and above is as follows:
module.exports = { //... optimization: { splitChunks: { chunks: ‘async‘,//默认只作用于异步模块,为`all`时对所有模块生效,`initial`对同步模块有效 minSize: 30000,//合并前模块文件的体积 minChunks: 1,//最少被引用次数 maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: ‘~‘,//自动命名连接符 cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, minChunks:1,//敲黑板 priority: -10//优先级更高 }, default: { test: /[\\/]src[\\/]js[\\/]/ minChunks: 2,//一般为非第三方公共模块 priority: -20, reuseExistingChunk: true } }, runtimeChunk:{ name:‘manifest‘ } } }
4.3 Code splitting instances
Note: The demo and configuration files used in the instance are placed in the attachment.
Single page Application
Single-page apps have only one portal file, and splitChunks
the primary role is to split the referenced third-party libraries. As can be seen from the sub-package results below, node_modules
the third-party references in the are separated out and placed in the vendors-main.[hash].js
.
Multi-page Application
The case of multi-page application is slightly complicated, with the example of "Webpack4: Legato in the Evolution" article in the Code segmentation process, the source of dependency is:
entryA.js: vue vuex component10kentryB.js: vue axios component10kentryC.js: vue vuex axios component10k
The package that you get after the code is split as shown:
? splitChunks
provides a more precise segmentation strategy, but it seems that it is not possible to html-webpack-plugin
dynamically resolve the injection of the split code directly through configuration parameters, because the subcontracting name is indeterminate. This scenario chunks:‘async‘
does not exist when using the default configuration, because the reference code of the async module does not need to be <script>
injected into the file as a label html
.
When the chunks
configuration item is set to all
or initial
, there is a problem, for example, in the example above, the html-webpack-plugin
excludeChunks
page and about two chunk can be removed by configuring in, but cannot be ruled out in advance Vendors-about-page This chunk because there is no way to know if a chunk will be generated before packing. This scenario the author did not find a ready-made solution, the need for this scenario readers may be able to use html-webpack-plugin
the event extension to deal with such scenarios, you can also use a compromise, that is, the first time after packaging records the newly generated chunk name, as required to fill html-webpack-plugin
in the chunks
configuration item.
4.4 Results Analysis
Bundle Buddy
the analysis tool or webpack-bundle-analyser
plug-in can see the impact of the pre-and post-subcontracting on the extraction of public code (images from the reference blog):
Five. Reference and annex Description
"1" in the attached file description:
webpack.spa.config.js
--Single page application code segmentation configuration Instance
main.js
--Single page application portal file
webpack.multi.config.js
--Multi-page application code Segmentation configuration Example
entryA.js
, entryB.js
, entryC.js
--3 portals for multi-page applications
"2" Reference: "Reduce JavaScript payloads with Code splitting"
webpack4.0 Conquer (4)--javascript & Splitchunk