Code splitting-04 of Vue package optimization

Time:2020-10-24

When it comes to the booming front-end circle, there are not only various frameworks, such as Vue, react, angular and so on, but also the development of packaging tools is in full swing, with a hundred schools of thought contending; from the early kings browserify, grunt, gulp, which won the throne later, and fis3, the next generation of packaging artifact rollup; in browserify, grunt, gulp, rollup, Webpack can take a look at some of the comparisons. What we want to explore in this article is that webpack is the absolute overlord of the current packaging tool.

Webpack Package optimization
Webpack Package optimization

Webpack is the default packaging scheme of the major mainstream frameworks. There are complete Chinese and English documents on how to use webpack. Moreover, each mainstream framework has corresponding cli configuration, so it is not included in the scope of discussion. In terms of product level, how to make the built package small in size and run fast, it is necessary to constantly explore the practice, refine and upgrade, so as to achieve the best. This paper will discuss the optimization of webpack packaging volume from the following aspects (Note: webpack practice version: 3.3.0)

With the passage of time, webpack has been constantly optimized and iterated; up to now, it has been updated to v4.8. *; in this version of webpack 4, she has done a lot of optimization on the original basis, and also introduced a lot of new features. In the new version, we will get more module types and support for. MJS, better default values, more concise mode settings, more intelligent to split chunks, and new splitchunks to define code blocks, and so on. In the project upgraded to the new version of webpack, there will be a qualitative leap in the speed of package construction, the volume & quantity of code blocks, and the running efficiency. For the latest consultation and tutorial resources of webpack, we recommend paying attention to webpack tutorial. After many attempts and explorations, we have integrated its various configuration and optimization experience into the Vue boilerplate template, with notes attached. We hope that it can help the friends who are preparing to upgrade and optimize webpack. Of course, we also welcome your valuable opinions and suggestions( [email protected] ) 。

Positioning the reasons for large webpack
Here, we recommend using webpack bundle analyzer — webpack plug-in and cli utility. She can display the content bundle as an interactive and intuitive tree view, so that you can understand what is really introduced in the package you are building; with her, we can find out what modules it is composed of, find out the out of date existence, and then optimize it. We can do it in the project package.json The following command is injected into the file to facilitate the operation of NPM run analysis, which will be opened by default http://127.0.0.1 : 8888 for display.

“analyz”: “NODE_ENV=production npm_config_report=true npm run build”

webpack-bundle-analyzer
webpack-bundle-analyzer

Of course, there are also webpack chart and webpack analysis of the same type. These two sites are also constructed in a visual way, so that you can clearly see the components of the module. However, to be a little troublesome, you need to run the following command to generate the JSON file required for tool analysis:

1
2
3
4
webpack –profile –json > stats.json
//This command is available if you want to run the specified weback file
webpack –config build/webpack.prod.conf.js –profile –json > stats.json
Introducing dllplugin and dllreferenceplugin
Dllplugin and dllreferenceplugin provide a way to split software packages in a way that greatly improves build time performance. The principle is to build a specific third-party NPM package module in advance, and then introduce it through the page. This can not only make the vendor file can be greatly reduced, but also greatly improve the component speed. In view of the space, please refer to: webpack.dll.conf .js。

External introduction module (CDN)
Today’s front-end development, of course, is to use ES6 or even higher versions, so it’s more fun to get up. However, due to browser compatibility problems, Babel transformation is still used. The Babel Polyfill also has to be introduced to ensure compatibility; for example, moment, which is commonly used in project development, Lodash, etc., are very large. If it is necessary to introduce it, consider introducing it from outside, and then specify it with the help of externals. Webpack can handle it so that it does not participate in packaging, but can still be accessed in the code through the global mode of CMD, AMD or window / global.

1
2
3
4
5
6
7
8
9
10
//Specified in webpack
externals: {
// ‘vue’: ‘Vue’,
// ‘lodash’: ‘_’,
‘babel-polyfill’: ‘window’
}
//
<script></script>
<script></script>
What needs to be added is in externals: key is the package name of require, and value is the global variable.

Make each third package “valuable”
Determine the necessity of introduction
If the project adopts MVVM pattern framework and bidirectional data binding, then class libraries like jQuery need not be introduced at all, at least it can be said that there is no need to introduce it. If you still have some concerns about this, you can refer to you right not need jQuery; you can solve the problem by writing a few lines of code natively. It is really not easy to introduce such a huge object and add trouble.

Avoid using class library references
If this kind of situation occurs, not only the whole packing volume, but also the loss. Once the project is large, it is difficult to ensure that each class library introduced is useful, especially for secondary development. Therefore, it is necessary to make use of the tools. Classes such as eslint are strongly recommended This kind of tool can not only effectively avoid the occurrence of similar situations (also applicable to the detection of ordinary variables), but also make the team code style as similar as possible. To know that the code is enough to comply with the rules, it can also make the compression tool more effective in compressing code. What’s more Are you happy?

Try to use modular introduction
If jQuery does not really need to be introduced, many people will agree; however, for tools such as lodash, not everyone will build a wheel. However, can the introduction of a full package of 400KB make your heart and liver tremble? Fortunately, lodash provides a modular way of introduction, which can be introduced on demand

1
2
3
4
5
6
7
import { debounce } from ‘lodash’
import { throttle } from ‘lodash’
//Write it as follows
import debounce from ‘lodash/debounce’
import throttle from ‘lodash/throttle’
If you are a good programmer, do you find it troublesome to write like this? Well, Congratulations, this problem has been solved; the existence of lodash webpack plugin and Babel plugin lodash (in combination) solves this problem. It can automatically change the lodash of full path reference into modularization and import according to use (as shown in the following example); moreover, the required configuration is very simple, so we will not repeat it here (warm tip: when some special methods are involved, we need to pay attention to it).

1
2
3
4
//Introduction of components, automatic conversion
import _ from ‘lodash’
_.debounce()
_.throttle()
What’s more, even if you use the above method, it’s not fast enough. It’s inconvenient to write import once for every file used. It is preferable to introduce the methods required by the project uniformly, add them as needed, build a local lodash class library, and then export them to the framework layer (for example Vue.prototype )For global use, see Vue modular import lodash for details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Under the helper folder lodash, unify the methods you need
import _ from ‘lodash’
export default {
cloneDeep: _.cloneDeep,
debounce: _.debounce,
throttle: _.throttle,
size: _.size,
pick: _.pick,
isEmpty: _.isEmpty
}
//Injection into the global situation
import _ from ‘@helper/lodash.js’
Vue.prototype.$_ = _
//Application in Vue component
this.$_.debounce()
Introduce more appropriate packages as much as possible
As a front-end developer, you must know the existence of momentum JS (parse, validate, manipulate, and display dates in JavaScript.); more importantly, you must know that it is very useful, but its body is very plump (plump). Without considering this, do you have the impulse to rebuild wheels? SpaceTime: A lightweight way to manipulate, traverse, compare, and format dates and times across planet Earth。 A new class library with an API similar to monent is much smaller in size (of course, it is observed that it is less flexible); date FNS: Modern JavaScript date utility library, like lodash, can support modularity; and recently developed DAY.JS : Fast 2kB alternative to Moment.js with the same modern API。 If you know these or more, how do you choose?

(update @ 2018-05-10) the Google Chrome labs team has built a warehouse on GitHub: optimize your libraries with webpack. For how to better use webpack, it gives a lot of good suggestions on how to write code, which is worth reading, which helps to further the volume of the built package.

Load module asynchronously on demand
As for the optimization of front-end development, it is important to merge requests and resources as much as possible, such as common request data merging, compression merging JS, constructing sprite chart, etc. (of course, it should be appropriate, pay attention to the volume, not too large); but at the same time, it should also be loaded asynchronously according to the needs, so as to avoid unnecessary waste of early success. Webpack also has built-in support for this aspect. If you use Vue to change a component (and all its dependencies) to asynchronous loading, all you need is to change the following:

1
import Foo from ‘./Foo.vue’
It should be written as follows:

1
const Foo = () => import(‘./Foo.vue’)
In this way, other components or other modules that the component depends on will be automatically divided into corresponding chunks to realize asynchronous loading. Of course, it also supports the partition of components into blocks, and the components in the same group are packaged in the same asynchronous chunk. In this way, it can effectively restrain the JavaScript package from being too large, and make the use of resources more reasonable.

Production environment, compress obfuscation and remove console
In the modern development of medium-sized and above scale, it has become the industry consensus to distinguish development environment, test environment and production environment, and treat them differently according to their needs; if possible, there will be pre release environment. For the production environment, compression obfuscation can effectively reduce the package volume; at the same time, if you can remove the frequently used console instead of simply replacing it with an empty method, it is also a wonderful small optimization. If you use the uglifyjsplugin plug-in to compress the code, add the following configuration to remove the console from the code:

1
2
3
4
5
6
7
8
new webpack.optimize.UglifyJsPlugin({
compress: {

warnings: false,
drop_console: true,
pure_funcs: ['console.log']

},
sourceMap: false
})
New function of webpack 3: scope hosting
Up to now (17-08-06), the latest version of webpack is 3.4.1; webpack in version 3.0 provides a new function: scope hosting, which is also translated as “scope promotion”. Just add a new plug-in to the configuration file to make the code file packaged by webpack smaller and faster

1
2
3
4
5
module.exports = {
plugins: [

new webpack.optimize.ModuleConcatenationPlugin()

]
}
It is learned that both scope hosting and tree shaking were originally implemented by rollup. In personal practice, although the injection of this function has an impact on the packing volume, it is not obvious. If you are interested, you can try it. For information about this function, please refer to the new function of webpack 3: scope hosting.