preface
In the process of webpack packaging, there are often several megabytes of app.js file, which is the first file loaded by the web page. Due to the execution sequence from top to bottom, the previous script will block the page rendering when loading, resulting in the white screen time. So how do we speed up web rendering? One way is a reasonable subcontracting strategy.
Project description
Source stamp GitHub, preview stamp here
A simple blog project, the project itself is not big, but through the phenomenon to see the essence, or can explain some problems.
Refer to the module
Vue-cli4 (similar to 3) uses the iView component for the UI, but also highlights. Js for highlighting code blocks, marked library for converting markdown syntax, jquery and other external libraries. In the absence of any optimization, the subcontracting situation is shown in the figure below.
The vendors are large, taking up 90% of the screen, and the total project size is almost the vendors’ size, typically top-heavy. The remaining 10% is almost all jquery, and our own code takes up less than 5% of the volume. If you are interested in running the development environment on the server, you can see how slow it is to load. 30 seconds of white screen time is not a blow-up.
To optimize
Configuration externals
Webpack’s externals option works when we use an external library, such as jquery, which creates a namespace globally with ($) to store the corresponding methods, vue(vue), vue-Router (VueRouter), Element-ui, et cetera, that’s what it means.
Externals can be configured so that webPack ignores these libraries and automatically mounts global variables in the global environment. You can import the libraries through the CDN, so that the corresponding dependencies can be extracted and loaded later. Such as:
/**
* vue.config.js
*/
configureWebpack: config => {
config.externals = {
marked: 'marked',
jquery: '&'// If there is a special symbol, it is best to enclose it in quotes, for example:'highlight.js': 'hljs'}}}Copy the code
Here’s how it works:
Jquery is gone, highlight.js is gone, marked is gone. Vendors start at 1M => 300KB, and then we can introduce these libraries at the bottom of the HTML:
Since highlight.js is a bit time-consuming to highlight the code, I implemented it in WebWorker, so the corresponding CDN was introduced in Woker using importScript, which I won’t repeat here.
The effect is still obvious. But there is still room for improvement.
Note: Placing them at the bottom of the page can speed up page rendering, provided that these libraries are not required for page initialization. This will result in an error in the initialization page where variables are not defined.
Since the pages of vUE and VUe-Router need to be used as soon as they are loaded, even if they are changed to CDN, they need to be placed at the top of the page. The actual experience is similar, but it is still very troublesome. Therefore, I use another way for such necessary dependence.
Configure the cacheGroups option
Let’s take a look at the scaffolding built-in default configuration. Run vue UI in the project root directory to enter the visual interface and select inspect to execute the task:
Find relevant configurations as follows:
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors'.test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true}}}}Copy the code
CacheGroups literally means cacheGroups, which define subcontracting chunks. Extracting these dependencies into a module when conditions are met is a key configuration for splitChunks. This is where WebPack determines how to split modules.
As you can see above, vendors use the test option to rematch, packaging all dependencies used under node_modules into a module called chunk-Vendors.
You might be asking, jquery is also in node_modules, so why isn’t it vendors? Because I reference it in the component, it’s packaged with the component.
Suppose the following reference statements occur in more than two components:
import $ from 'jquery'
Copy the code
The second rule, Common (minChunks 2), is extracted and packaged into a file named chunk-common. In cases where several rules are met at the same time, priority is used to set the weight and decide whom to listen to.
There are a lot of other attributes that I won’t expand here, but if you’re interested, you can go to Baidu. Now that you know that, it’s easy.
Too many or too few modules is no good, not that extreme. Clustering reduces the number of requests and splitting speeds up the download, but at the same time, the former increases the download time and the latter increases the time it takes for the connection to be established and released. The pros and cons of this need to be weighed according to the specific situation.
In general, modules that are used earlier are loaded first. In this project, I divided the dependencies into:
- Vue buckets
- UI components
- Rely on other
The configuration is as follows:
/**
* vue.config.js
*/
configureWebpack: config => {
Object.assign(config.optimization.splitChunks.cacheGroups, {
'view-design'{// Separate component library name:true, / / the nametrueIt will automatically nametest: /[\\/]view-design[\\/]/,
priority: 10,
chunks: 'initial'}, vue: {// split vue bucket name:true.test: /[\\/]vue(.+?) [\\/]/, priority: 5, chunks:'initial'}}}})Copy the code
The other dependency processing rules are predefined vendors and Common, and I leave them unchanged.
Actually, that’s pretty much it. The point of subcontracting is to improve transmission efficiency, not to compress volume.
other
According to the need to introduce
Component libraries, such as Lodash and Moment, are equipped with plugins for webPack and imported on demand. Externals can also be used appropriately. Some component libraries, such as Element-UI, iView, etc., can be imported on demand using babel-plugin-import, as described in the official documentation. With the on-demand introduction, externals is no longer needed, and personal feelings are no longer necessary.
About the CDN
Since the concurrent requests under the same domain name are restricted by the browser, some of them are 4 or 6. Different browsers seem to have differences. Therefore, when introducing many CDNS, different source sites can be considered.
- Front-end static resource library
- staticfile CDN
You said BootCDN? How can I say? At first, I had a good impression of bootCDN, and I liked the interface. Later, I found that CDN was unstable and could not be accessed frequently. That’s not to say you can’t use it, but you can write a little demo
About DllPlugin
You can skip this one if you’re not interested
I recently used this to do something similar to the cacheGroups described above. I actually knew about cacheGroups before I knew about DllPlugin. Because the configuration was a bit cumbersome, I delved into it and felt pretty good about myself, only to learn later that the plugin was obsolete. I don’t know, a little frustrated, after all the work.
But if you think about it, webpack3 uses this plugin to package commonly used but not often changed libraries directly into HTML, such as vue, vuex, vue-router, etc. But it turns out that he packages all of them, and if he comes across a component library, he packages a bunch of them.
This plug-in was originally used to speed up builds because static resources don’t compile every time. However, since you need to write an additional WebPack configuration, the configuration is relatively tedious. There are automation plug-ins, but times have changed. Now that WebPack 5 is around the corner, webPack build speeds are perfectly fine, and with the ability to use cacheGroups for subcontracting, there’s no need to use it.
What? Why write this if it’s out of date? Because I am not happy π€¬, I am uncomfortable, psychological gap, ha ha, I want to record down.
The last
Now this year, not webpack are embarrassed to say that he is engaged in the front end. Recently, I have written a lot of demos and encountered a lot of problems in the process. It is these problems that make me further understand Webpack. I always wanted to write an article to summarize, but the problems I encountered were so fragmentary that I didn’t seem to be able to write an article. Finally, I caught this opportunity.
After reading feel good words, remember to point a zan Ao, thank π
The related resources
- Front-end static resource library
- staticfile CDN
- BootCDN
- Making the source code
- Front-end optimization: Extracting third-party JS using DLLS (DllPlugin DllReferencePlugin)