Advanced webpack-usage of caching and independent packaging, advanced webpack

Source: Internet
Author: User

Advanced webpack-usage of caching and independent packaging, advanced webpack

This article introduces the advanced webpack-Cache and independent packaging usage and shares it with you, hoping to help you

Let's take a look at the most basic webpack Configuration:

var path = require('path'); module.exports = { entry: './src/index.js', output: {  filename: 'bundle.js',  path: path.resolve(__dirname, 'dist') }}

The lodash library is introduced in index. js:

Src/index. js:

import _ from 'lodash';  function component() {  var element = document.createElement('div');  element.innerHTML = _.join(['Hello', 'webpack'], ' ');   return element; }  document.body.appendChild(component());

After packaging, only one bundle. js will be generated. In this way, the browser will load the lodash library that will not be changed each time the resource file is to be loaded, which is very inefficient.

If you access the browser each time, the browser downloads the resources again. Because the network may be slow to obtain resources, the page may not be loaded for a long time, which is inefficient and unfriendly, the browser will cache the resources, to avoid getting resources through the network for each access.

However, due to browser cache, new problems may occur. If we do not change the resource file name when deploying a version, the browser may think that it is not updated and will use its cached version.

In this way, we need to solve two problems:First, separate the packaging file. Second, solve the cache problem.

Const path = require ('path'); const webpack = require ('webpackage'); module. exports = {entry: {common: ['lodash '], app :'. /src/index. js'}, output: {filename: '[name]. [hash]. js', path: path. resolve (_ dirname, 'dist')}, plugins: [new webpack. optimize. commonsChunkPlugin ({name: 'common' // It refers to index. lodash library introduced by js})]}

Major changes:

  • Add plug-in: CommonsChunkPlugin. Extract the introduced library and rename it to implement code separation.
  • The output adds hash to the name. After each package, the hash value is different, which solves the browser cache problem.

Result: index. js is packaged as app. [hash]. js, and lodash introduced by index. js is packaged as common. [hash]. js. This solves the browser cache problem and achieves the separation of static resource code and source code, but the new problem arises again.

After the first package (note the name in the Asset column ):

Each time we modify the source code, we package it again, not only generating app. [hash]. js hash values by index,

And common. [hash]. the hash value of js is also changed when it is the same as the hash value of app (you can test it yourself, package webpack it once, and modify the index. js package again ).

This is not the expected result. Although the source code hash change solves the problem that the browser uses the cached version, if the common. if the hash value of js also changes, the browser also needs static code common that will not be changed every time, which wastes network resources and is very inefficient.

Note: In this case, the dist directory will generate too many junk files, and the CleanWebpackPlugin plug-in is used in actual use.

Copy codeThe Code is as follows:
New CleanWebpackPlugin (['dist']) // you can add it to the plug-in array to clear the files packaged in the package folder before each package.

If the index is modified, only the hash value of the generated app changes, and the hash value of common does not change, then we can achieve our goal, both the cache library and source file changes can be identified.
In the output, change [name]. [hash]. js to [name]. [chunkhash]. js to generate a unique hash value for each file:

Const path = require ('path'); const webpack = require ('webpackage'); module. exports = {entry: {common: ['lodash '], app :'. /src/index. js'}, output: {filename: '[name]. [chunkhash]. js', path: path. resolve (_ dirname, 'dist')}, plugins: [new CleanWebpackPlugin (['dist']), new webpack. optimize. commonsChunkPlugin ({name: 'common' // It refers to index. lodash library introduced by js})]}

(Note: Do not use [chunkhash] In the development environment because it increases the Compilation Time. Separate the configuration of the development and production modes and use [name] In the development mode. js file name. Use [name] in production mode. [chunkhash]. js file name. If HotModuleReplacementPlugin is used in this case, compilation will fail !)

After the configuration is complete, pack the webpack:

Chunkhash is a hash generated based on the file content. It can be seen that the hash values generated by the app and common are different ([name]. [hash]. js is used for packaging ).

Modify index. js and package it again:

It is strange that although the common and app generate separate hash values, the hash values of index. js and common are modified.

The reason is: to minimize the size of the generated file, webpack uses the identifier instead of the module name, generates the identifier during compilation, maps it to the block file name, and puts it in a JS object named chunk manifest. The point is !! When we use CommonsChunkPlugin to separate code, the code that is separated (the lodash library in this article is packaged as common .), It will be moved to the last entry in the entry for packaging by default (the first entry is index. js ). Importantly, chunk manifest will be packaged together with these separated codes !!!

After we change the source code, we will not only update the app's hash value, but also generate a new ing, and then the new ing will be packaged together with the resource code, because chunkhash generates a hash Based on the content, after the resource code of the new ing object chunk manifest is packaged, the hash will naturally change. In turn, the new hash generated will invalidate the long-term cache.

What we need to do next is to separate manifest. Here we use a CommonsChunkPlugin function that is rarely known to anyone. We can extract manifest from the build after each modification by specifying the name not used in the entry, this plug-in will automatically extract the content we need to a separate package.

Therefore, configure another CommonsChunkPlugin:

Const path = require ('path'); const webpack = require ('webpackage'); module. exports = {entry: {common: ['lodash '], app :'. /src/index. js'}, output: {filename: '[name]. [chunkhash]. js', path: path. resolve (_ dirname, 'dist')}, plugins: [new CleanWebpackPlugin (['dist']), new webpack. optimize. commonsChunkPlugin ({name: 'common' // It refers to index. lodash library introduced by js}), new webpack. optimize. commonsChunkPlugin ({name: 'manifest '// used to extract manifest})]}

After webpack is packaged:

Here we can prove that the aforementioned manifest has been packaged into common !!! Take a closer look at the previous figure: the common Size is 547kb. Here, the common Size is 541kb, and the manifest Size is exactly 5.85kb. The total Size is exactly 547kb.

Then we modify index. js and package it again:

You can find it here !! We modified the source code, and the hash value of common is no longer changed! Here we can achieve the goal of not caching source code cache resource files.

But don't be too happy !! We made a very small modification and exchanged the order of app and common in the entry (compared with the previous code segment ):

Const path = require ('path'); const webpack = require ('webpackage'); module. exports = {entry: {app :'. /src/index. js', common: ['lodash ']}, output: {filename:' [name]. [chunkhash]. js', path: path. resolve (_ dirname, 'dist')}, plugins: [new CleanWebpackPlugin (['dist']), new webpack. optimize. commonsChunkPlugin ({name: 'common' // It refers to index. lodash library introduced by js}), new webpack. optimize. commonsChunkPlugin ({name: 'manifest '// used to extract manifest})]}

After packaging:

Comparing the previous image, we found that the hash value of common has changed !! In addition, the app hash of the index. js content has not changed at all, but the order has changed!

Pay attention to the module resolution sequence of this graph and the previous graph ([1], [2], [3 ). The first lodash resolution is found in the previous figure, while the last lodash resolution is now.

This is why hash changes: this is because each module. id is incremental Based on the default resolution order (resolve order. That is to say, when the resolution order changes, the ID also changes, so the hash value also changes.

Some people may decide that we will not change the entry sequence in webpack. config. js, so I will not encounter this problem. The answer is no. Except for no, you can ensure that all resource files are written at the top of the entry. Otherwise, this may occur:

If the entry order is app-> common, the resolution order is index. js → lodash. If print. js is introduced in index. js, the resolution order is changed to index. js → print. js-> lodash.

As mentioned above, we have not changed the entry order in the entry, the resolution order will change, and the common hash will still happen and cannot be cached.

Here we will introduce a new component: HashedModuleIdsPlugin: Generate ID based on hash (NamedModulesPlugin also has the same effect, but it is generated based on the path name, which is more readable, and the Compilation Time will be relatively long ). In this way, the module. id does not use a numeric identifier, but uses hash:

Const path = require ('path'); const webpack = require ('webpackage'); module. exports = {entry: {common: ['lodash '], app :'. /src/index. js'}, output: {filename: '[name]. [chunkhash]. js', path: path. resolve (_ dirname, 'dist')}, plugins: [new CleanWebpackPlugin (['dist']), new webpack. hashedModuleIdsPlugin (), // introduce the new webpack plug-in. optimize. commonsChunkPlugin ({name: 'common' // It refers to index. lodash library introduced by js}), new webpack. optimize. commonsChunkPlugin ({name: 'manifest '// used to extract manifest})]}

It was found that there were numbers in [], and now there are some characters,

Next, we will change the app and common order, modify index. js at will, and package again:

Now, the hash of common has not changed, but the hash of the content app has changed. This is what we want.

References:

Webpack document-Cache

Webpack independent packaging and cache Processing

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.