Code splitting-02 of Vue package optimization

Time:2020-10-26

preface
I used vuecli to make a blog, which is a single page project with about ten routes.

Package it with NPM run build directly, and there is a huge JS file of 1m.

clipboard.png

Try to mount it to the server first
Boy, it seems that half a century has passed since the loading time

clipboard.png

The first screen page loaded a full 9 seconds, just loading that big file took 8 seconds
This has to be optimized. No user can tolerate a 9s white screen without closing the page

In the process, I also moved the project from vuecli 2. X to vuecli 3, so I will introduce some differences and similarities in optimization

analysis
Vuecli 2. X comes with analysis tools
Just run NPM run build — report

If it is vuecli 3, install the plug-in first

cnpm intall webpack

bundle

analyzer

save

dev

And then in the vue.config.js Configure webpack in

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’
)

}

}

}

Then run NPM run build — report

A diagram of project packaging will be opened in the browser, so that the sizes of various bundle files can be compared intuitively

clipboard.png

You can see that all the dependencies and all the routes in the project are packed into the same file

In addition, in the browser, you can also view the code usage through convert

clipboard.png
The red ones are downloaded but not used

Route lazy loading
When packaging an application, the JavaScript package becomes very large, affecting the page loading.
If we can divide the components corresponding to different routes into different code blocks, and then load the corresponding components when the routes are accessed, it will be more efficient.

It is obviously inappropriate to download all the component files corresponding to routes at the beginning. This is just like downloading an app, so we need to use route lazy loading

clipboard.png

In router.js File, the original static reference mode

import

ShowBlogs

from

‘@/components/ShowBlogs’

routes
:[
path
:

‘Blogs’
,
name
:

‘ShowBlogs’
,
component
:

ShowBlogs

]

Change to

routes
:[
path
:

‘Blogs’
,
name
:

‘ShowBlogs’
,
component
:

()

=>

import
(
‘./components/ShowBlogs.vue’
)

In this way, the routing files can be packaged separately. Only when a given route is parsed, the routing components will be downloaded

clipboard.png

The files that need to be loaded on the first screen have turned into orange parts, which have been shunted out by the kids for 300K

If it’s in vuecli 3, we need to do one more step

Because vuecli 3 turns on prefetch (preload module) by default to obtain the content that users may access in the future

On the first screen, you can download the more than a dozen routing files at one go

So we’re going to turn this feature off. In the vue.config.js Set in

Refer to the official website:

clipboard.png

After setting, the first screen will only load the components of the current page route

Element UI load on demand
clipboard.png

The first 56K UI package needs to be loaded
The original introduction method introduced the whole package:

import

ElementUI

from

‘element-ui’

Vue
.
use
(
ElementUI
)

But in fact, the only components I use are buttons, pagination, tables, inputs and warnings
So we need to quote:

import

{

Button
,

Input
,

Pagination
,

Table
,

TableColumn
,

MessageBox

}

from

‘element-ui’
;

Vue
.
use
(
Button
)

Vue
.
use
(
Input
)

Vue
.
use
(
Pagination
)

Vue
.
prototype
.
$alert
=

MessageBox
.
alert

Note the difference in the registration methods of the message box, and although we use alert, we do not need to introduce the alert component

Add (Vue cli 3 needs to install Babel plugin component first) in the. Babelrc file:

plugins
:

[

[

“component”
,

{

“libraryName”
:

“element-ui”
,

“styleLibraryName”
:

“theme-chalk”

}

]

]

clipboard.png
The element UI is much smaller, but you can see the obvious one table.js It occurred to me that the table component is only used in the background management page and does not need to be registered globally, so we deleted it main.js Table and tablcolumn, and register locally in the background component

import

{

Table
,

TableColumn

}

from

“element-ui”
;

components
:

{

“el-table”
:

Table
,

“el-table-column”
:

TableColumn

},

clipboard.png
The table is split into the routing file

Repeated packaging of components
As you can see in the figure above, two routing files are referenced codemirror.js Cause duplicate Download
We can modify the configuration of Commons chunkplugin in the config file of webpack

minChunks
:

3

If you change 3 to 2, the packages that have been used twice or more will be pulled out and put into the public dependency file. However, since the home page also has reusable components, the home page will also download the public dependency file

clipboard.png

The yellow and grey sections are downloaded from the front page
After half a day’s demolition, it’s back to the origin

Of course, we can continue to fiddle with the configuration of Commons chunkplugin to solve this problem
But in the new version of webpack, commons chunkplugin is replaced by split chunkplugin with higher degree of freedom

That’s why I moved my project to vuecli 3 (using webback4)
It is optimized by default, and only the gray part (235k) will be downloaded from the home page

gzip
After unpacking, we compress it with gzip
Install compression webpack plugin

cnmp i compression

webpack

plugin

D

In vue.congig.js Introduce and modify webpack configuration in

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/
,

//Match file name

                threshold

:

10240
,

//Compress the data over 10K

                deleteOriginalAssets

:

false

//Delete original file

})]

}

}

clipboard.png
We can see that the files above 200K are compressed to less than 100k

In the server, we also need to do the corresponding configuration
If the browser sending the request supports gzip, send it a gzip file
My server is built with the express framework
Just install compression and you can use it

const
compression
=

require
(
‘compression’
)

app
.
use
(
compression
())

Note that the latter sentence should be placed before all other middleware registrations

Final effect
clipboard.png
First screen loading resources 198k, loading time 1s, 90% faster than the original speed

Postscript: do you want to split CSS
Another difference between vuecli 3 and vuecli2. X is that
Vuecli 3 will open a CSS separation plug-in extracttextplugin by default

Each module’s CSS file will be separated, a full 13 CSS files, and our home page has requested 4, spending a lot of resource request time.

We can vue.config.js To close it:

css

:

{

//Do you want to use the CSS separation plug-in extracttextplugin

extract

:

false
,

//Open CSS source maps?

sourceMap

:

false
,

//CSS preset configuration item

loaderOptions

:

{},

//Enable CSS modules for all CSS / pre processor files

modules

:

false

},

clipboard.png

clipboard.png

There is no CSS folder in the packaged files.

Instead, an integrated JS file is responsible for injecting all the styles at the beginning.

The number of files loaded on the first screen is reduced, but the volume becomes larger, so there is no big difference in the speed of final measurement.

Therefore, whether to split CSS depends on the specific project.

summary
Performance optimization is a very pleasant process, but also a deep hole, there are too many things, this article opened the beginning, hoping to help you