Author: enhancement of night The original address: segmentfault.com/a/119000001…
preface
I did a blog with Vuecli earlier. It was a single page project with about 10 routes packaged directly into NPM Run build and a huge JS file of 1M
Let’s just mount it to the server and try it boy it’s been loading for like half a century
It took 8s to load that big file. This has to be optimized. No user can tolerate 9s of blank screen without closing the page
In the process, I also migrated the project from Vuecli 2.x to Vuecli 3, so I’ll cover some of the similarities and differences in optimization
Analysis of the
Vuecli 2.x comes with an analysis tool just run NPM Run build –report
For Vuecli 3, install the plug-in first
NPM intall webpack – bundle – analyzer – save – dev
Then configure webPack in vue.config.js
chainWebpack: (config) => {/* Add analysis tools */ if (process.env.node_env === 'production') {if (process.env.npM_config_report) {config .plugin('webpack-bundle-analyzer') .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) .end(); config.plugins.delete('prefetch') } } }Copy the code
Then run NPM run build –report
! Note: For very old projects may not run successfully, please refer to Baidu for specific methods.
A project packaging diagram opens in the browser to visually compare the size of individual bundles
You can see that all the dependencies in the project, all the routes, are packaged into the same file
Alternatively, in the browser, converge to see how the code is being used
The red ones are the ones that are downloaded but not used
Route lazy loading
JavaScript packages can become very large when packaged to build applications, affecting page loads. It would be much more efficient if we could split the components corresponding to different routes into different code blocks and then load the components only when the routes are accessed.
It is obviously not appropriate to download all the component files corresponding to the route in the first place. It is like downloading an app, so we need to use lazy route loading
In the router.js file, the original static reference
import ShowBlogs from '@/components/ShowBlogs'
routes:[ path: 'Blogs', name: 'ShowBlogs', component: ShowBlogs ]
Copy the code
Instead of
routes:[ path: ‘Blogs’,name: ‘ShowBlogs’,component: () => import(‘./components/ShowBlogs.vue’)
Dynamically imported as a function so that the respective routing files can be packaged separately and the routing components are downloaded only when a given route is parsed
The file that needs to be loaded on the first screen turns into the orange part, which is shunted out by the boys for 300K
If it is in vuecli 3, we need to do more work step Because vuecli 3 default open prefetch (preloaded module), early get the user may access the contents of the future This a dozen routing file on the first screen will, are downloaded at a stretch So we have to close the function, Set in vue.config.js
Refer to the official website:
Once set up, the first screen will load only the components of the current page route
Element-ui loads on demand
The first screen needs to be loaded with dependencies, of which element-UI takes up 568K of the entire package.
import ElementUI from ‘element-ui’
Vue.use(ElementUI)
But the only components I’m really using are buttons, pagination, tables, input and warnings so we’ll reference them as needed:
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from ‘element-ui’;
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)
Vue.prototype.$alert = MessageBox.alert
Notice the difference in MessageBox registration methods, and we use alert, but we don’t need to introduce an alert component
Add to the. Babelrc file (vue-cli 3 requires babel-plugin-component) :
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
Copy the code
The element-UI is much smaller, but when we see the table.js, we realize that the table component is only used by the admin page and does not need global registration, so we remove the references to the table and TablColumn in main.js and register them locally in the background component
import { Table, TableColumn } from "element-ui";
components: {
"el-table": Table,
"el-table-column": TableColumn },
Copy the code
The table is split into a routing file
Component repackaging
As you can see in the figure above, there are two routing files that reference codemiror.js and cause repeated downloads. We can modify the CommonsChunkPlugin configuration in the webpack config file
minChunks: 3
Changing 3 to 2 will pull out packages that have been used twice or more and put them into a public dependency file, but since the home page also has reusable components, it will also download this public dependency file
Home page download yellow and gray part of the tear down along while, back to the origin
Of course, we could keep fidgeting with the CommonsChunkPlugin configuration to solve this problem, but in the new webPack, the CommonsChunkPlugin is replaced by SplitChunksPlugin, which is more flexible and advanced
This is why I migrated the project to vuecli 3 (using webpack4) which is optimized by default and only downloads the gray section on the home page (235K)
gzip
After unpacking, we will use gzip to install compression-webpack-plugin
nmp i compression-webpack-plugin -D
Introduce and modify the WebPack configuration in vue.config.js
const CompressionPlugin = require('compression-webpack-plugin') configureWebpack: (config) => {if (process.env.node_env === 'production') {// Modify configuration for production environment... Config. Mode = 'production' return {plugins: [new CompressionPlugin ({test: / \. Js $| \. HTML $| \. CSS /, / / matching filename threshold: DeleteOriginalAssets: false})]}}Copy the code
You can see that files over 200K are compressed down to 100K
On the server we’re going to have to configure that if the browser that’s sending the request supports GZIP, we’re going to send it a GZIP file and my server is built with the Express framework and you can use Compression if you install compression
const compression = require(‘compression’)
app.use(compression())
Note that this last sentence precedes all other middleware registrations
The final result
The first screen loads 198K resources, taking 1s to load, which is 90% faster than the original speed
Postscript: Whether to split the CSS
Another difference between Vuecli 3 and Vuecli2. x is that vuecli 3 will enable a CSS ExtractTextPlugin by default. The CSS files of each module will be separated, a total of 13 CSS files, and our home page requested four. We can turn it off in vue.config.js
CSS: {extract: false, // enable CSS source maps? SourceMap: false, // CSS preset configuration item loaderOptions: {}, // enable CSS modules for all CSS/pre-processor files.modules: false},Copy the code
Pack out file, directly without the CSS folder Instead, integrate a js file, is responsible for all injection style from the start First screen load file number decreases, but the volume is larger, eventually down speed not too big difference So, split on whether to CSS, specific project specific analysis
conclusion
Performance tuning is a very enjoyable process, but it’s also a pit, and there’s so much going on here that I hope this article will help you out