I have been learning webpack recently. Once upon a time, I always felt that webpack system was huge and difficult to master, so I always avoided learning it. However, the great Lu Xun once said: there are too many things in the world will be unable to master and make you agitated, the best solution is to brave it and start doing! So start with the CommonsChunkPlugin
Although this article is relatively simple, but still need a little knowledge of Webpack, if you have no contact with Webpack, it is recommended to go to the official documentation and Webpack 3, from the beginning to give up to understand the basics of Webpack is a good ~
Basic configuration
The CommonsChunkPlugin is an optional feature for creating a single file (aka chunk) that contains a common module for multiple entry chunks. By stripping out the common modules, the resultant files can be loaded once at the beginning and then stored in the cache for later use. This gives a speed boost because the browser quickly removes the common code from the cache, rather than loading a larger file every time a new page is visited.
In simple terms, this is a bit like wrapping a function. Separate the constant from the changing, so that the constant can be reused efficiently, flexible configuration of the change. Next, we will optimize our project according to this principle. Now let’s see what the virtual project looks like
Create a new index. HTML template and entry index.js file with simple configuration as follows:
Index.html:
<! doctype html> <html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{{ vue_test }}</p>
</div>
<div class="jq_test"></div>
</body>
</html>Copy the code
index.js
:
import Vue from 'vue';
import $ from 'jquery';
new Vue({
el: '#app',
data: {
vue_test: 'vue is loaded! '}}) $(function() {$('.jq_test').html('jquery is loaded! ')})Copy the code
For demonstration purposes, the code is very simple and doesn’t need much explanation. Next, configure webpack.config.js as follows:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: {
index: path.join(__dirname, 'index.js')
},
output: {
path: path.join(__dirname, '/dist'),
filename: 'js/[name].[chunkhash].js'
},
resolve: { alias: { 'vue': 'vue/dist/vue.js' } },
plugins: [
new CleanWebpackPlugin(['./dist']),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new BundleAnalyzerPlugin(),
]
};Copy the code
The CleanWebpackPlugin is mainly used to clean up files in the dist directory so that you don’t have to do it manually each time you pack. The HtmlWebpackPlugin is designed to create an HTML template in the dist directory and automatically insert dependent JS. BundleAnalyzerPlugin is mainly used to generate the dependencies contained in the packaged JS file. If this is done, the following dependencies will be generated:
As you can see, the generated index.js file contains vue and jquery.
Optimization for the first time
In general, the libraries in our projects change less, and the business code is. You need to find a way to separate the class libraries and package the business code separately. In this way, the browser can cache the js files of the class library after the hash is added, optimizing the user experience. This is where the CommonsChunkPlugin comes in. We add CommonsChunkPlugin to plugins in the webpack.config.js file and configure it as follows:
Plugins: / / /... after code new webpack.optimize.Com monsChunkPlugin ({name:'vendor',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules') === 0)}}),]Copy the code
This is done by using CommonsChunkPlugin to generate a JS file named vendor, which extracts dependencies from node_modules in the index.js entry file. In this case, vue and jquery. The picture looks like this:
This seems to solve our problem by extracting and extracting the dependent libraries into separate packages and caching them for the browser to cache. However, it’s not that simple. You can change the entry’s index.js code at will and pack it again:
Desperate to find that the hash of vendor.js file has changed. In short, this is caused by the change of module identification, and the correction method is also quite simple, which is to use CommonsChunkPlugin to extract the module again, to deposit the unchanged libraries, and to extract the changed ones out. Add the following code:
Plugins: / / /... after code new webpack.optimize.Com monsChunkPlugin ({name:'vendor',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor'.'index'"})"Copy the code
After packing, there is a js file named manifest in the dist/js directory. At this point, no matter how you change the code of index.js, the packaged vendor.js hash will not change.
But wait, before you want to call it a day, consider this scenario: As the project continues to iterate, dependencies in a vendor are constantly added and removed, causing its hash to change, which is clearly not in our interest. How can this be resolved?
Once again, to optimize
Since the CommonsChunkPlugin can extract modules according to our needs and dependent external modules may be constantly changing, why not extract the base dependency module as one file and other dependencies such as plug-ins as a separate file?
To put it simply, for example, in our project vUE is the basic dependency and must be used, while jquery and others are an added class library and may change later. Packaging vue as a separate file is good for the browser cache, because the vue file cache will still work regardless of whether you add more libraries or delete jquery later. So we can do this by creating a new entry:
entry: {
index: path.join(__dirname, 'index.js'),
vendor: ['vue'],},Copy the code
The main purpose here is to indicate which dependencies need to be packaged separately. Then make the following changes in your plugins:
Plugins: / / /... after code new webpack. HashedModuleIdsPlugin (), the new webpack.optimize.Com monsChunkPlugin ({name:'vendor',
minChunks: Infinity,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
},
chunks: ['index'],
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor'.'common'.'index'"})"Copy the code
The HashedModuleIdsPlugin plugin is used to keep the module ID referenced by the module unchanged. The CommonsChunkPlugin extracts the dependencies specified in the entry, minChunks: Infinity, in order for the plugin to ignore everything else and simply extract the files in the array. Then modify the original vendor, rename it common, and specify that it extracts dependencies from node_modules from the entry index.js. Finally, extract the WebPack runtime functions and their module identifiers to form the Manifest. Run webPack and build it like this:
You can see that vue and jquery are packaged separately into two files. We tried to add a new dependency vuex, and the result is as follows:
In this way, our optimization purpose is achieved, unchanged are extracted, the change can be dynamically configured ~
summary
This is the CommonsChunkPlugin for WebPack, but there are many optimizations, such as enabling compression, removing comments, and so on. As the project grows in size, the CommonsChunkPlugin may not be the optimal solution for extracting code. In terms of speed of packaging and control of build refinement, the DLLPlugin provides better performance. One of the charms of WebPack is to combine different plug-ins for different scenarios to achieve our goals.
All code will be uploaded to Github. Star ~ Thank you!