vue 性能优化 白屏

背景

  • 需求:vue h5内嵌到app中,发现在app中显示h5时会出现首屏白屏,大概1-2s左右,但是在浏览器中没有白屏的知觉
  • 参考文档:https://juejin.im/post/5bee7dd4e51d451f5b54cbb4
  • 分析:

    • 本地启动服务,在chrome浏览器控制台中分析如下,发现首屏白屏长达2200-400 = 1800ms,竟然有这么长的白屏时间


      200ms左右时间在加载app.js,考虑是否可以路由懒加载

    • npm install webpack分析工具,然后在vue.config.js中配置,查看打包情况,如下

      1
      npm install webpack-bundle-analyzer  - -save -dev

    在vue.config.js中配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      chainWebpack: (config) => {
    // 分析工具
    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')
    }
    }
    }

    然后 npm run build – report



  • 优化方案
    • 路由懒加载
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // lazy load
      const Download = () => import('@/views/Download.vue');
      const route = [
      {
      path: '/download',
      name: 'download',
      component: Download
      }
      ];

      export default route;
此时时间降低 到1200ms-400ms = 800ms,此时js.chunk.js压缩到 547.45k
![](/img/first-onload/07.png)
此时build包的情况
![](/img/first-onload/08.png)
![](/img/first-onload/09.png)

- 利用webpack对超过10k以上的包进行gzip压缩
- 对UI组件 antd-vue 进行按需加载
![](/img/first-onload/10.png)

  - 进行以上分析以后,会发现,在FP与FCP阶段,还是有1s左右的首屏白屏,这里的解决方案是与UI和交互协调,引入骨架屏或者loading,这里在app加载之前引入loading,然后再APP创建的时候将这个loading移除即可,如下:
    public下index.html
  
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  <!DOCTYPE html>
` <html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0" />
<link rel="icon" href="<%= BASE_URL %>logo.ico" />
<link rel="icon" href="<%= BASE_URL %>logo.ico" rel="shortcut icon" />
<link rel="icon" href="<%= BASE_URL %>logo.ico" rel="Bookmark" />
<link rel="apple-touch-icon" sizes="152x152" href="<%= BASE_URL %>logo.png" />
<img id="shareImg" src="<%= BASE_URL %>sharelogo.jpg" width="0" height="0" />
<title>iFLYBUDS</title>
<script type="text/javascript">
(function(window, document) {
let deviceWidth = document.documentElement.clientWidth;
if (window.orientation == 90 || window.orientation == -90) {
if (deviceWidth > 1334)
deviceWidth = 1334;
document.documentElement.style.fontSize = deviceWidth / 13.34 + 'px';
} else {
if (deviceWidth > 750)
deviceWidth = 750;
document.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
}
})(window, document)
</script>
<style type="text/css">
#Loading {
width: 100vw;
height:100vh;
background: #1C1F29;
z-index: 1000;
margin-top: -18px;
}
.loader_inner {
display: flex;
flex-direction: column;
top: 50%;
left: 50%;
position: absolute;
-webkit-transform: translateY(-50%) translateX(-50%);
transform: translateY(-50%) translateX(-50%);
}
.loader_info {
width: 100%;
font-family: PingFang SC;
font-style: normal;
font-weight: normal;
font-size: 0.3rem;
line-height: 0.52rem;
text-align: center;
color: #A2A5B8;
}
.loader_inner_cicle {
position: relative;
width: 0.72rem;
height: 0.72rem;
margin: auto;
border:1px solid #fff;
}
#loader8 {
margin: auto;
float: left;
position: relative;
text-indent: -9999em;
border-top: 0.1rem solid #2e3043;
border-right: 0.1rem solid #2e3043;
border-bottom: 0.1rem solid #2e3043;
border-left: 0.1rem solid #80809e;
-webkit-animation: load8 2s infinite linear;
animation: load8 2s infinite linear;
}
#loader8,
#loader8:after {
border-radius: 50%;
width: 0.72rem;
height: 0.72rem;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but kuaidu-wx-pay doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="Loading">
<div class="loader_inner">
<div id="loader8"></div>
<div class="loader_info">正在加载,请稍后</div>
</div>
</div>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>`
然后在App创建之前将这个div移除,如下: App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <template>
<div id="app">
<router-view />
</div>
</template>
<script >
export default {
data () {
return {}
},
created() {
let loading = document.getElementById('Loading');
if (loading !== null) {
document.body.removeChild(loading);
}
}
}
</script>
打完包以后的首屏加载时间降低到900ms,如下: ![](/img/first-onload/11.png) ![](/img/first-onload/12.png)