Vue首屏加载提升
本文部分思路源自:
vue-cli 3.0 build包太大导致首屏过长的解决方案 (opens new window)
发布前端项目时因chunk-vendors过大导致首屏加载太慢,Vue Build时chunk-vendors的优化方案 (opens new window)
# 开头
在没有进行优化之前,我的网站加载js文件需要25s,这大大的降低了其他人访问我网站的兴趣,所以适当的优化是不可少的。
# 优化点一
压缩成gzip格式:
安装插件
npm install --save-dev compression-webpack-plugin
1
vue.config.js配置插件
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
transpileDependencies: ["vuetify"],
outputDir: __dirname + "/../server/web",
publicPath: process.env.NODE_ENV === 'production'
? '/web/'
: '/',
configureWebpack: config => {
if (isProduction) {
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
}))
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
nginx配置
# gzip config
gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
1
2
3
4
5
6
7
2
3
4
5
6
7
完整示例
server {
listen 80;
# gzip config
gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
root /usr/share/nginx/html;
location / {
# 用于配合 browserHistory 使用
try_files $uri $uri/ /index.html;
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
# rewrite ^/(.*)$ https://preview.pro.loacg.com/$1 permanent;
}
location /api {
proxy_pass https://preview.pro.loacg.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
listen 443 ssl http2 default_server;
# 证书的公私钥
ssl_certificate /path/to/public.crt;
ssl_certificate_key /path/to/private.key;
location / {
# 用于配合 browserHistory 使用
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass https://preview.pro.loacg.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
打包后的gzip文件可以达到原有的20%
# 优化点二
路由懒加载
结合Vue的异步组件再结合webpack的代码分割,我们可以轻松的实现路由懒加载。
// 安装插件 syntax-dynamic-import
cnpm install --save-dev @babel/plugin-syntax-dynamic-import
// 修改babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: ['@babel/plugin-syntax-dynamic-import']
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// 修改路由组件的加载(router/index.js)
import Vue from "vue";
import VueRouter from "vue-router";
import NotFound from "../views/404";
import Comment from "../views/Comment" //我这个组件有bug,就不做懒加载了
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: resolve => require(['../views/Home'], resolve)
},
{
path: "/home",
component: resolve => require(['../views/Home'], resolve)
},
{
path: "/home/:id",
component: resolve => require(['../views/ArticleList'], resolve),
props: true
},
{
path: "/home/article/:id",
component: resolve => require(['../views/Article'], resolve),
props: true
},
{
path: "/image",
component: resolve => require(['../views/Image'], resolve),
},
{
path: "/article",
component: resolve => require(['../views/ArticleRecent'], resolve),
},
{
path: "/image/:id",
component: resolve => require(['../views/ImageList'], resolve),
props: true
},
{
path: "/site",
component: resolve => require(['../views/Site'], resolve),
},
{
path: "/site/:id",
component: resolve => require(['../views/SiteList'], resolve),
props: true
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
},
{
path: "/search/:title",
component: resolve => require(['../views/SearchList'], resolve),
props: true
},
{
path: "/404",
component: resolve => require(['../views/404'], resolve),
},
{
path:"/privacy",
component: resolve => require(['../views/Privacy'], resolve),
},
{
path:"/log",
component: resolve => require(['../views/Log'], resolve),
},
{
path:"/link",
component: resolve => require(['../views/Link'], resolve),
},
{
path:"/comment",
component: Comment
},
{ path: "*", component: NotFound }
];
const router = new VueRouter({
routes
});
export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# 优化点三
启用CDN加速
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
transpileDependencies: ["vuetify"],
outputDir: __dirname + "/../server/web",
publicPath: process.env.NODE_ENV === 'production'
? '/web/'
: '/',
configureWebpack: config => {
if (isProduction) {
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
}))
}
#分离不常用代码库转为cdn引用
config.externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
"vuetify":"Vuetify"
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 在public文件夹的index.html 加载,一些css,js能用cdn的都可以用
<!-- CND -->
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.runtime.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet" type="text/css">
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="external nofollow" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/gitalk/1.6.0/gitalk.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vue-loading-overlay@3/dist/vue-loading.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.min.css" rel="stylesheet">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 优化点四
阿里云配置全站加速,这个大家自己去阿里云看加好了
# 结果
基于以上优化,我的js编译出来的文件大小由6m降低为1.4m,document加载时间由25s缩短为5m以内,降低了200%,所以优化是有用的。
编辑 (opens new window)
上次更新: 2022/08/29, 16:40:19