By: Small Potato Blog park: www.cnblogs.com/HouJiao/ Nuggets: juejin.cn/user/243617…
preface
One of the company’s existing products is realized by using vUE V2.0 framework, and the supporting packaging tool is WebPack V3.0. The entire project is about 80 + VUE files, which is not a huge project.
But each headache is that the packaging takes about a minute on average, and several files are “big” after packaging, that is, the file volume is too large.
Recently, I want to make some modifications to see if I can make some optimizations on the basis of previous ones. I will record them and share them with you.
Webpack package optimization
Packaging optimization for WebPack is generally considered from two aspects: shortening the packaging time and reducing the size of the file after packaging. These two aspects also happen to be the problems I need to solve before.
So let’s take a look at how these two aspects are implemented.
Shorten packing time
We all know that WebPack runs a process like a production line, where each process is executed sequentially. It is obvious that webpack packaging can be more efficient if there are fewer things to do per process or more people working on each process.
1. Reduce the search scope of files by Loader
You can configure the loader exclude option to tell the loader that it can ignore a directory. Or configure the Include option for loader to tell loader to process only the specified directory. Because the fewer files the Loader processes, the faster the execution will be.
It is common to configure the exclude option for babel-loader.
// webpack.config.js
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.js$/,
loader: 'babel-loader'.exclude: /node_modules/ // Exclude is a regular}}}]Copy the code
This configuration tells babel-loader to ignore the node_modules directory when converting JS code. This configuration is done because most of the packages referenced in node_modules are compiled and do not need to be processed by babel-loader.
2. Leverage caching
The official explanation for webpack caching is roughly this: when caching is turned on, webPack builds attempt to read data from the cache to avoid costly recompilation every time they run.
So how do you turn on caching when you compile code?
◕ cacheDirectory
The first option is to configure cacheDirectory for babel-loader to enable caching for babel-loader.
// webpack.config.js
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.js$/,
loader: 'babel-loader? cacheDirectory'.exclude: /node_modules/}}}]Copy the code
◕ cache - loader
The second is to use cache-loader.
NPM install cache-loader –save-dev; Then configure in Webpack:
// webpack.config.js
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.js$/,
loader: [
'cache-loader'.'babel-loader'
]
exclude: /node_modules/
},
{
test: /\.ext$/,
use: [
'cache-loader'.// Other loader
// ...],}]}}Copy the code
The official suggestions for using cache-loader are as follows: Add this loader before some loaders that consume a lot of performance to cache the results to disks. Saving and reading these cache files can be time consuming, so use this loader only for performance heavy loaders.
It can be considered simply that if a Loader processes a large number of time-consuming tasks during execution, it is judged that the performance of the Loader is expensive. We can try to enable caching for the loader. Of course, if the actual packaging time does not decrease after caching is enabled, it indicates that enabling caching has little impact on the performance of the Loader.
More about the cache, the contents of the loader can view: https://www.webpackjs.com/loaders/cache-loader/
◕ hard - source - webpack - the plugin
The third way to enable caching is to use the hard-source-webpack-plugin. NPM install –save-dev hard-source-webpack-plugin; NPM install –save-dev hard-source-webpack-plugin; The basic configuration is as follows:
// webpack.config.js
/ / introduction
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
// Enable HardSourceWebpackPlugin only in production
if (process.env.NODE_ENV === "production") {
module.exports.plugins = (module.exports.plugins || []).concat([
new HardSourceWebpackPlugin()
])
}
Copy the code
More about hard – source – webpack – the use of the plugin to view: https://github.com/mzgoddard/hard-source-webpack-plugin
The above three ways to enable caching are different, but you can see the results of their caching on our disk as long as you configure them.
3. Multithreading
Multithreading is to assign one thing to more than one person to do, theoretically speaking, it can improve the completion efficiency of one thing.
◕ happyhack
We all know that the entire running and building process of WebPack is single-threaded due to node’s single-threaded mode.
So the first way to enable multithreading is to extend the execution of the Loader in Webpack from single-threaded to multi-threaded. The implementation of this approach relies on the HappyPack plug-in.
NPM install –save-dev happypack; The simplest configuration is as follows:
// webpack.config.js
/ / introduction
const HappyPack = require('happypack');
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.js$/.// Use loader to call happypack
loader: 'happypack/loader'.exclude: /node_modules/}}}]// Happypack is configured only in the production environment
if (process.env.NODE_ENV === "production") {
module.exports.plugins = (module.exports.plugins || []).concat([
new HappyPack({
// re-add the loaders you replaced above in #1:
loaders: 'babel-loader',}})])Copy the code
This configuration means that the matching.js source code is passed to HappyPack, which converts them in parallel using a loader-specified loader (in this case, babel-Loader).
In this most basic configuration, three threads are processed in parallel by default. You can also customize the number of threads by configuring the Thread option.
// webpack.config.js
new HappyPack({
// re-add the loaders you replaced above in #1:
loaders: 'babel-loader'.// Customize the number of threads
threads: 2,})Copy the code
With regard to thread Settings, the official recommendation is to use a shared thread pool to control the number of threads: However, if you’re using more than one HappyPack plugin it can be more optimal to create a thread pool yourself and then ‖ Configure the plugins to share that pool, minimizing the idle time of threads within it. It’s better to create a thread pool yourself and then configure these plug-ins to share that pool to minimize idle time for the threads in it.)
Creating a thread pool is also simple:
// webpack.config.js
const happyThreadPool = HappyPack.ThreadPool({ size: 4 });
Copy the code
In addition to creating a specific number of threads as described above, you can also create a number based on the number of CPU cores:
// webpack.config.js
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length-1 });
Copy the code
Once the threadPool is created, specify a shared threadPool via a threadPool:
// webpack.config.js
// Omit some code here
new HappyPack({
// re-add the loaders you replaced above in #1:
loaders: 'babel-loader'.// Use a shared thread pool
threadPool: happyThreadPool
})
Copy the code
The final useful configuration item is the verbose option, which allows happypack to print execution logs:
// webpack.config.js
// Omit some code here
new HappyPack({
// re-add the loaders you replaced above in #1:
loaders: 'babel-loader'.// Use a shared thread pool
threadPool: happyThreadPool,
// Outputs execution logs
verbose: true
})
Copy the code
More content about HappyPack can view: https://github.com/amireh/happypack
Unfortunately, the author of the plugin announced on Github that he would no longer be updating the project.
◕ thread - loader
Thread-loader is similar to Happypack in that it extends the loader’s processing threads to reduce packaging time. NPM install thread-loader –save-dev; The simplest configuration is as follows:
// webpack.config.js
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.js$/,
loader: [
'thread-loader'.'babel-loader'
]
exclude: /node_modules/}}}]Copy the code
You need to configure thread-loader to other loaders.
More about the content of the thread – loader can view: https://www.webpackjs.com/loaders/thread-loader
◕ webpack - parallel - uglify - the plugin
In order to reduce the size of the packed file, we usually compress the file, such as deleting newlines, deleting comments and so on. That common is to compress JS, the most basic is to use the official webpack uglifyjs-webpack-plugin plugin; However, the plug-in is single-threaded compression code, which is relatively inefficient. And webpack-parallel-ugli-fi -plugin is a multi-thread compression JS code plug-in;
NPM install webpack-parallel-uglify-plugin; The simple configuration is as follows:
// webpack.config.js
ParallelUglifyPlugin (ParallelUglifyPlugin
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
// Configure ParallelUglifyPlugin only in production environments
if (process.env.NODE_ENV === "production") {
new ParallelUglifyPlugin({
workerCount: 4.// Start several sub-processes to perform compression concurrently. The default is the number of cPU cores currently running on the computer minus 1
cacheDir: './cache/'.uglifyJs: {output: {beautify:false.// No formatting required
comments:false.// Do not keep comments
},
compress: {warnings:false.// Uglify]s does not print a warning when dividing unused code
drop_console:true.// Delete all console statements, compatible with Internet Explorer
collapse_vars:true.// Inline variables that are defined but used only once
reduce_vars:true.// Retrieve static values that occur more than once but are not defined as variables to reference}}}}),Copy the code
After packaging, can significantly improve the compression efficiency of JS code.
Use this plug-in with versioning concerns, and if you have problems building code after configuration, try switching to a lower version. This time, my Webpack version is V3.6, and the version of webpack-parallel-Uglify-Plugin installed directly is V2.0.0. There was an error in the later packaging, so after lowering its version to 0.4.2, it can be packaged normally.
The important thing to note about multithreading is that the more threads there are, the shorter the build time is not. Because the child thread needs to send the result to the main process after it has finished processing, the main process does the summary processing, which also takes time. So the optimal number of threads can be achieved through practice.
4. Dynamic link library
Generally, when we package a VUE project, we will package the code of vue, VUe-Router, AXIos and other plug-ins into a file with our code, and the code content of these plug-ins will not change unless the version changes. So every time you package a project, you’re essentially repackaging the code for these plug-ins, which obviously wastes a lot of time.
The term dynamic link library is actually borrowed from the concept of dynamic link library in the operating system. The implementation of WebPack is to package the plug-ins described earlier into a separate file. When a module needs to reference the plug-in, it will link to the corresponding plug-in through the generated JSON file. This way we don’t have to deal with these plug-ins repeatedly, either in the development environment or in the build environment. Let’s look at the configuration and use of dynamic link libraries.
First we need to create a new webpack.dll.config.js file, which is itself a WebPack configuration file that is mainly used to separate third-party plug-ins.
// webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const DllPlugin = require('webpack/lib/DllPlugin');
// The directory where the detached third-party library files are stored
const dllPath = "webpackDLL";
module.exports = {
// entry file entry configuration needs to separate third-party plug-ins
entry: {
echarts: ['echarts'].// This configuration represents the separation of the Echarts plug-in
},
// Output file
output: {
path: path.join(__dirname, dllPath), // Separate the location of the third party plug-in
filename: "[name]-dll.[hash:8].js".// The name of the detached third-party plug-in file
library: '_dll_[name]' // The name of the third-party plug-in. If other modules need to reference the plug-in, use this name
},
resolve: {
extensions: ['.js'.'.vue'.'.json'].alias: {
'vue$': 'vue/dist/vue.esm.js',}},plugins: [
// Clear the previous DLL file
new CleanWebpackPlugin(),
// Use the DLLPlugin for separation
new webpack.DllPlugin({
// Path to the generated *.manfest.json file
path: path.join(__dirname, dllPath, "[name]-manifest.json"),
// Name needs to be the same as output.library
// The *.manfest.json is then generated with a name field whose value is the one we configured here
name: '_dll_[name]'}})];Copy the code
The meanings of the preceding configuration items are described in the comments. Let’s do a package with this configuration item and see the result. To do this we need to add a script script to package.json.
// package.json
{
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --hot --port 4500 --host 192.168.1.10"."build": "cross-env NODE_ENV=production webpack --progress --hide-modules"."dll": "webpack -p --progress --config ./webpack.dll.config.js"}}Copy the code
The new DLL script uses webpack.dll.config.js as the configuration file to perform packaging tasks.
After the script is successfully executed, directories and files are generated on the local PC.
Echarts.dll.2a6026f8.js is our separate echarts plug-in, echarts-manifest.json is the previous json file we said.
If a module needs to reference echarts after the third-party library file is separated, how to reference the corresponding echarts.dll.2a6026f8.js file?
This is where the DllReferencePlugin comes in: configure the DllReferencePlugin’s manifest file to map the name of the dependent module to the corresponding plug-in. This step needs to be configured in webpack.config.js:
// webpack.config.js
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
module.exports = {
entry: {},
output: {},
module: {},
plugin: [
new DllReferencePlugin({
// Manifest is the *.manifest.json file that was packaged earlier
manifest: path.join(__dirname, 'webpackDll'.'echarts-manifest.json'),}}),]Copy the code
After the above configuration is complete, if we are in the development environment, run NPM run dev to open the browser, we will find that the page cannot be displayed normally, and the console has an error message:
This is because we also need to manually import the separate plug-in file in the entry template file index.html.
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
<! -- Manual import -->
<script type="text/javascript" src="./webpackDLL/echarts-dll.2a6026f9.js"></script>
</body>
</html>
Copy the code
There is no problem refreshing the page after that.
/webpackDLL/*.2a6026f9.js. In this case, if the project is packaged and deployed, the index.html reference is still./webpackDLL/*.2a6026f9.js. It is clear that the reference path of this resource is wrong only in the local environment; Moreover, the output path of a packaged project is typically configured separately, such as the dist directory, and only files in that directory are deployed.
So just the previous configuration, the project will not work properly after deployment.
There is obviously a crude and simple way to solve this problem: The path introduced in index. HTML is still the same, and the packaged code is still in the dist directory, but after the packaging is completed, the corresponding webpackDLL plug-in directory and files are manually copied to the dist directory, so that the dist directory can be directly deployed to the server to run normally.
In addition to this way, we can use some plug-ins for WebPack to complete this function, which will not be demonstrated here, you can try to do it yourself.
Reduce the size of packaged files
1. Compress files
◕ image - webpack - loader
For image compression, choose image-webpack-loader. Normally, the installation command is as follows: NPM install image-webpack-loader –save-dev, but there are a lot of errors when using this command. Install image-webpack-loader: CNPM install image-webpack-loader –save-dev
The most basic configuration for image-webpack-loader is as follows:
// webpack.config.js
module.exports = {
entry: {},
output: {},
plugin: [].module: {
rules:[
{
test: /\.(png|jpe? g|gif|svg)(\? . *)? $/,
exclude: [resolve("src/icons")].use: [{loader: "url-loader".options: {
limit: 1024*10.name: path.posix.join("assets"."images/[name].[hash:7].[ext]"),}}, {loader: 'image-webpack-loader'.// Compress the image
options: {
bypassOnDebug: true,}}]}]}}Copy the code
More about the content of the image – webpack – loader please see: https://www.npmjs.com/package/image-webpack-loader
Cache-loader 4.1.0 requires WebPack4.0.0 cache-loader 3.0.1 requires 3.0.1
◕ webpack - parallel - uglify - the plugin
This plug-in is used to compress JS code (multi-threaded compression), and the usage has been described previously, but not here.
Reducing the size of a file by compressing it also leads to an increase in the webPack time, because it adds a few steps to the process of doing one thing.
2. Remove the third-party library
CommonsChunkPlugin is an official webpack plug-in that can be configured to separate common modules.
Webpack V4 no longer supports this plug-in and uses SplitChunksPlugin instead. However, since this project uses WebPack V3, SplitChunksPlugin is not covered here.
First we need to configure the public modules we need to isolate in the Entry option of webpack.
module.exports = {
entry: {
main: ["./src/main.js"].// The original entry file
vender: ['echarts'] // Separate the echarts module}},Copy the code
We then need to configure the output of this public module in plugin:
module.exports = {
plugins: [new webpack.optimize.CommonsChunkPlugin({
name: 'vender'.// The entry vender configured in the corresponding entry
filename: '[name].js' // The separated module has the name option as the filename, i.e. Vender.js}})]Copy the code
After the configuration is complete, package the project and you will see an additional file named vendor.js in the package result.
At this point, we can see that the js file size of the components using Echarts is significantly reduced after packaging.
If we need to continue to separate some other public modules, we can continue to configure in Entry:
module.exports = {
entry: {
main: ["./src/main.js"].// The original entry file
vender: ['echarts'.'vue'.'other-lib']}}Copy the code
If the plugin configured above remains unchanged, the public module configured by Entry. vendor will be packaged into vendor.js file uniformly. If too many public modules are configured, the size of the extracted vendor.js file will be too large.
The solution to this problem is to separate third-party plug-ins using the dynamic link library described earlier, which will be covered later in the practice section.
3. Delete useless code
It is inevitable that a product will generate some obsolete code in the process of iteration, or that when we use a front-end component library, only a small part of the component library is used, and when we package, the content of the whole component library is packaged. Either discarded code or unused component code can be called useless code, so obviously removing this useless code can reduce the size of the packaged file.
◕ purgecss webpack -- the plugin
PurgeCSS is a tool for removing unused CSS code. NPM install purgecss- webpack-plugin-save-dev
This plug-in needs to be used in conjunction with the Mini-CSS-extract-Plugin, so the mini-CSs-extract-plugin also needs to be installed. Note, however, that the Mini-CSS-extract-plugin requires WebPack V4.
Then configure in the WebPack configuration file:
// webpack.config.js
const path = require('path')
const glob = require('glob')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const PurgecssPlugin = require('purgecss-webpack-plugin')
const PATHS = {
src: path.join(__dirname, 'src')}module.exports = {
entry: './src/index.js'.output: {
filename: 'bundle.js'.path: path.join(__dirname, 'dist')},optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles'.test: /\.css$/,
chunks: 'all'.enforce: true}}}},module: {
rules: [{test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"]]}},plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",}).new PurgecssPlugin({
paths: glob.sync(`${PATHS.src}/ * * / * `, { nodir: true}})}),]Copy the code
More information about purgecss-Webpack-Plugin can be found at https://www.purgecss.cn/.
◕ tree - shaking
Tree-shaking is shown in Webpack:
The official documentation shows that this can be done with sideEffects in WebPack V4, and shows us some basic examples.
As for this optimization scheme, it has not achieved the desired effect in both the understanding of some relevant concepts and the practice of the project. Therefore, this optimization point is only sorted out here. The specific configuration and effect of the optimization program in the project will not be demonstrated, so as not to mislead you.
Tree-shaking is not shaking, but shaking is not shaking. Tree-shaking is not shaking. Tree-shaking is shaking.
1. 【 your Tree - Shaking and no egg] (https://segmentfault.com/a/1190000012794598)
2. 【 Tree - Shaking performance optimization principle of practice - article] (https://juejin.cn/post/6844903544756109319)
Package analysis tool
In addition to the specific optimizations we described earlier, there are two commonly used package analysis tools that can help us analyze the build process and the size of the packaged file.
1.speed-measure-webpack-plugin
Speed-measure-webpack-plugin Is a Webpack plug-in that measures the packaging speed and outputs the execution time of each loader and plugin during the packaging process.
NPM install speed-measure-webpack-plugin; Then configure it in webpack.config.js:
// webpack.config.js
/ / introduction
const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
// Create an instance
const smw = new SpeedMeasureWebpackPlugin();
// Call the instance's smw.wrap and pass in the webPack configuration as an argument
module.exports = smw.wrap({
entry: {},
output: {}
module: {},
plugins:[],
})
Copy the code
After completing the above steps, we execute the NPM run build and see the package time information output by the plug-in.
From this information we can clearly see how long each plugin and loader took so that we can optimize for the parts that took longer.
2.webpack-bundle-analyzer
Webpack-bundle-analyzer is also a Webpack plug-in that creates an interactive tree diagram of all the packed files, including their size and contents.
It is also very simple to use, starting with installation: NPM install webpack-Budle-Analyzer; Once the installation is complete, you just need to write the following in the webPack configuration file:
// webpack.config.js
/ / introduction
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
Copy the code
After we run NPM run build, webpack will output the following log.
By default, a browser window pops up, opening http://127.0.0.1:8888/.
If the address is not automatically enabled, you can manually enter the address. At the same time, it is important to note the plug-in enabled by default on port 8888, if appear port usage, can on the default port configuration, details may refer to: https://www.npmjs.com/package/webpack-bundle-analyzer.
From the page we can clearly see the size of each file, which modules are introduced in the file, and the file size of each module. According to these contents, we can deal with some large files and some large modules in these large files.
conclusion
So far we have listed a number of specific WebPack optimizations and a simple configuration for each one. Next, we will apply these schemes to actual projects. Before practice, we will make a brief review and summary of the previous content.
The practice started
Everything is in place now, except practice. Let’s take a look at the effect of the above optimization scheme in the actual project.
Shorten packing time
First of all, we use speed-measure-webpack-plugin to analyze the packaging duration of the whole project.
It’s not a complete picture, but it shows you the important parts. According to the log information output by the time analysis tool, we can clearly see that the whole packaging takes 50 seconds, among which UglifyJsPlugin executes as long as 33 seconds, and other relatively time-consuming loaders execute.
As for shortening the packaging time, the optimization of the latter item is based on the optimization of the previous one, so the overall packaging time will be constantly shortened.
1. Use webpack-parallel-uglify-plugin instead of uglifyjs-webpack-plugin
According to the previous analysis, the first point we need to optimize is to use webpack-parallel-uglify-plugin instead of uglifyjs-webpack-plugin to compress JS code into multi-threading.
After extending js code into multithreaded compression, it is packaged.
This effect is really very obvious, the overall packaging time from 50 seconds -> 36 seconds; JS code is also compressed by 33 seconds -> 15 seconds, almost 50% less time.
2. Enable cache
The next optimization point is to enable caching. There are three ways to enable caching mentioned above, but in the practical application of this project, only the hard-source-webpack-plugin has obvious effect, and the other two have almost no effect.
After the hard-source-webpack-plugin is configured, the time taken for the first packaging will not change basically, which is still 30 seconds after we optimized the last step.
It will happen the next time you pack.
After the hard-source-webpack-plugin is configured, the first packaging duration does not change because there are no cached files at this time. Cached files are generated only after the first packaging is completed. After the second time in the packaging, directly read the cache file, the overall time is significantly shortened; In addition, it can be seen from the time analysis result of the second packaging that there is no time analysis of Loader, which also indicates that the packaging result is directly read from the cache.
The second packaging tested above builds on the first and does not change the code. In real development, most of the code is modified and packaged again. How does caching affect the packaging time in this case? Let’s give it a try.
Here I arbitrarily modified two.vue files, added a line of code to each, and packaged them.
After the file is modified, the corresponding cache file will be invalid, so we see the corresponding loader is executed again, and the overall packaging time is increased. However, in general, the plug-in can effectively shorten the packaging time.
3. Enable multi-threading
Earlier we said that multithreading is done by extending the execution process of the Loader in Webpack from single-threaded to multi-threaded. Because we have enabled cache before, the execution time of loader is very short, so it is basically ineffective to enable multithreading on the basis of enabling cache, and the fact has proved to be the same.
So in this step, I turned off the cache and used happypack to enable multi-threading for babel-loader and CSS-Loader respectively, but the final packaging time did not change much, it remained in the 30s.
The optimization scheme of enabling multi-threading has no obvious effect in this project, which may be due to the short processing time of loader in the project itself. Even with multithreading enabled, communication between threads and the final summary of threads takes the same time as single-threaded processing.
4. Dynamic link library
This time I used the DLLPlugin to separate the echarts and Element components.
// webpack.dll.config.js
module.exports = {
// Import file
entry: {
echarts: ['echarts'].element: ['element-ui']},// Other code omitted
}
Copy the code
At last, the packaging time was significantly reduced.
Finally, in the practice of DLL configuration, we found that there are two special points to pay attention to:
The first is the resolve configuration item in webpack.dll.config.js. In fact, at the beginning, the plug-in element-UI was separated according to some online configurations. Finally, after the whole project was packaged and deployed, the table of the Element-UI component could not be rendered.
After a bit of searching, I found a number of related issues on Element-UI github, saying that after using the DLLPlugin to separate the Element-UI, the table would not render and the tooltip control would not work. However, the official basically said that it is not the problem of Element-UI itself and put the issue as closed.
Finally, I went through the issues and added the Resolve configuration according to one of them.
The second thing to note is that we need to manually import the isolated third-party plug-in into the index.html entry template, and in production we need to copy the isolated plug-in code into the WebPack output directory for the project to run properly once deployed.
5. To summarize
By now, the optimization of shortening the packaging time has basically been completed. We have tried four schemes in total, and finally reduced the packaging time from the initial 50s to 6s, which shows a very obvious effect.
Reduce the size of packaged files
Before optimization, we still use Webpack-bundle-Analyzer to analyze the volume of packaged files.
Here I highlight two representative results as screenshots. One is the entry file main.js, where the larger module introduced is the element-UI core file element-ui.mon.js and the vue core file vue.esm.js; The other is total.js, which introduces bulky Echarts files.
1. Compress files
Previously, we introduced that compression of JS and images can reduce file size. In this project, webpack-parallel-Ugli-fi – Plugin has been configured to compress JS code, so we only try to compress image images.
After configuring image-webpack-loader, you’ll be surprised to find that not all images will be smaller, but some will be larger anyway.
There is no in-depth study on the abnormal result, so the optimization scheme is temporarily judged to be invalid for this project.
2. Remove the third-party library
According to the previous analysis, if the corresponding file size is reduced, the most direct way is to remove the larger third-party libraries such as Vue, Echarts, and Element-UI using CommonsChunkPlugin.
After separation, the file size of main.js and total.js decreases significantly: main.js changes from 1.5MB -> 755kB; Total. Js from 819 KB – > 29 KB.
However, the isolated vendor.js is 1.56MB in size.
3. Dynamic link library
Dynamically linked libraries are actually categorized as shortening the packaging time, but in fact they can effectively shorten the packaging time, and can also separate third-party libraries into different files, and solve the problems of CommonsChunkPlugin.
This time we used DLLPlugin to separate vue, Echarts, and Element.
// webpack.dll.config.js
module.exports = {
// Import file
entry: {
echarts: ['echarts'].element: ['element-ui'].vue: ["vue"],},// Other code omitted
}
Copy the code
Three plugins separated out:
After packaging, the size of main.js was reduced from 1.5MB to 800kB, and the size of the remaining files referenced to the Echarts plug-in was reduced from hundreds of kB to tens of kB.
conclusion
At this point, the packaging optimization practice of Webpack is completed, the overall packaging time is greatly reduced; Some large files are separated and the size of files is reduced effectively. However, some optimization schemes have no obvious effect in this project, or even have the opposite effect. As for the reasons, we have not studied them carefully at present.
Some of the optimizations described in this article may not be complete, and most of them apply to WebPack V3. Wekpack V4 has some optimizations enabled by default in many cases, so you should refer to them rationally. If there is an opportunity, I will try to upgrade the webpack version of the project in the later stage, and then summarize and share.
All at the same time, if it is real project optimization, the optimization of the scheme can not only focus on packaging length is lower or the file size is reduced, each optimized after the completion of the project practice also need to generate environment in the development environment and simple test was carried out on the project, if the project is running to illustrate this optimization scheme is successful. For example, in the DLL optimization scheme we practiced earlier, once the configuration is complete, you may feel complacent if you only focus on the packaging time and file size, but when you deploy the project to the server, you find that the project doesn’t run at all.
Finally, if you have any questions or find mistakes in this article, please point them out and make progress together.
A recent article
JavaScript execution context, really not you think so difficult page-skeleton-webpack-plugin primary exploration
Write in the last
If this article helps you, ❤️ follow + like + favorites + comment + forward ❤️ to encourage the author
Article public number first, focus on unknown treasure program yuan for the first time to get the latest article
Ink ❤ ️ ~