写在前面的话
公司最近项目已经进入使用阶段,从用户那边反应过来的问题,说小程序打开太慢,中间白屏几秒,于是想办法来做一个等待效果。
优化后效果
具体实现(已vue为例)
按照正常的思路,路由按需加载、cdn、GZIP压缩这一系列常规的优化方案都可以加快首屏渲染的速度,但是由于微信小程序webView官方并没有提供类似骨架屏加载动画的功能,我们在选用小程序嵌套webView进入网页时 仍然会有一段时间的白屏反应时间。
那么要想优化这一现象,我们就得知道在白屏这段时间中,浏览器做了什么。
来看看vue打包后index.html里面的内容
包括各个页面中的css样式 以及最为主要的两个js文件,文件占用的大小情况如下
我们可以看到,在未开启Gzip压缩之前最大的一个 js就已经有将近1M的大小,开启Gzip压缩之后减少到300多k 整体项目文件也逼近1M,微信小程序客户端将这些1M多的文件下载再解析dom展示给到用户中间的这段时间,页面就是白屏的。
既然已经了解到其中的过程 那么解决的方法也就来了。我们可以写一个占用空间非常小的静态加载中的页面临时过渡作为小程序webView加载中的等待页,在这个等待页中跳转到相关项目页面,这样一来就能极大的减少白屏过渡时间。
我们可以将它写在vue项目的public目录下,打包的时候一并上传到服务器。
当然这种方案,加载的速度跟手机的网络以及解析dom的速度成正比,如果在网络质量不好,与百元机上展示的情况下,效果不是特别明显。 大家可以酌情考虑。
示例代码
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<head>
<style type="text/css">
.first-loading-wrp {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 90vh;
min-height: 90vh;
}
.first-loading-wrp > h1 {
font-size: 24px;
font-weight: bolder;
}
.first-loading-wrp .loading-wrp {
display: flex;
align-items: center;
justify-content: center;
padding: 80px;
}
.dot {
position: relative;
box-sizing: border-box;
display: inline-block;
width: 64px;
height: 64px;
font-size: 64px;
transform: rotate(45deg);
animation: antRotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 28px;
height: 28px;
background-color: #1890ff;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: antSpinMove 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}
</style>
</head>
<body>
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin">
<i></i>
<i></i>
<i></i>
<i></i>
</span>
</div>
<h2>努力加载中...</h2>
</div>
<script>
init();
function init() {
const request = GetRequest();
// 这里需要注意 获取的oriUrl需要进行转义
let url = request['oriUrl'] || "";
if (url == "") {
console.log('未传递回调地址 oriUrl参数');
return;
}
url = decodeURIComponent(url)
delete request['oriUrl'];
let i = 0;
//其他get参数原封不动的传给网页
for (let key in request) {
console.log(key + ":" + request[key]);//json对象中属性的名字:对象中属性的值
url = `${url}${i == 0 ? '?' : '&'}${key + '=' + request[key]}`;
i++;
}
setTimeout(() => {
// 等待一秒 跳转页面
window.location.replace(url);
}, 1000)
}
function GetRequest() {
let url = location.search; //获取url中"?"符后的字串
let theRequest = new Object();
if (url.indexOf("?") != -1) {
let str = url.substr(1);
strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
}
console.log(theRequest, 'theRequest')
return theRequest;
}
</script>
</body>
</html>