H5性能优化与体验优化 您所在的位置:网站首页 前端如何优化网站性能模式 H5性能优化与体验优化

H5性能优化与体验优化

2024-07-17 20:36| 来源: 网络整理| 查看: 265

性能优化

H5的性能优化有一个很重要的指标——首屏加载速度。而我们一般所说的H5性能优化指的也是如何提升首屏加载速度。而我们常用的优化首屏速度的方案,可以大致总结为以下几种:

首屏资源懒加载,延迟加载首屏资源gzip和cdn加速减少js包大小图片裁剪或压缩

具体可以参考文章,一般优化后都能有不错的效果 。 随着我们项目用户数越来越多,对性能要求也越来越极致。为此,我想到了一些其他的方案。

一、页面数据本地缓存

用户的网络情况是是否复杂的,经常还会遇到弱网情况。可以将页面的数据缓存到本地,用户下次打开时无需网络请求就可以直接显示了。这可以大大加快用户看到页面内容的速度。

浏览器的本地缓存方案大致有以下几种:

localStorage:这是前端开发使用最多的一种缓存之一。可以用作持久化缓存。读写是同步,数据大时会阻塞主线程。只能存储string类型,存储容量只有2.5M到10M之间(不同浏览器不同)。Web SQL:前端数据库。但它兼容性不好,自测只有chrome浏览器支持,ie或微信内置浏览器都是不支持的。IndexedDB:浏览器提供的本地数据库。 特点: 键值对存储,简单易用。读写异步。访问数据库不会阻塞调用线程。存储空间大。一般来说不少于 250MB,甚至没有上限。支持事务,意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。支持二进制存储,可以直接存储对象。具有同源策略,安全。各浏览器兼容性不错,自测微信和QQ自带浏览器都是支持的。

于是我选择IndexedDB作为我们H5的缓存方案。 实现核心代码:

createOrOpenDb({ dbName, storeName, keyPath, indexOptions }) { const mIndexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB; const dbOpenRequest = mIndexedDB.open(dbName, this.dbVersion); return new Promise((resolve, reject) => { dbOpenRequest.onsuccess = (event) => { console.log(`${dbName} 打开或创建成功`); this.db = event.target.result; resolve(this.db); }; dbOpenRequest.onerror = (event) => { reject(event.target.error.message); }; dbOpenRequest.onupgradeneeded = (event) => { console.log(`${dbName} upgrade version : ${this.dbVersion}`); this.db = event.target.result; this.createObjectStore(storeName, keyPath, indexOptions); }; }); } createObjectStore(storeName, keyPath, indexOptions) { if (!this.db.objectStoreNames.contains(storeName)) { const objectStore = this.db.createObjectStore(storeName, { keyPath, }); objectStore.createIndex(keyPath, keyPath, { unique: true, }); for (const prop of indexOptions) { objectStore.createIndex(prop, prop, { unique: false, }); } console.log(`${storeName} 数据结构定义完毕`); } }, 二、JS预加载

我们H5项目使用的是Vue框架,比较复杂,存在大量多级页面。跳转到二级页面时,需要网络加载二级页面的js文件。为了提升页面间跳转的速度,我想到了是否可以在当前页面提前加载下一级页面的js文件?这样跳转到二级页面时,无需先请求js文件,可以直接显示。于是,我便开始了js的预加载方案的预研:

Web Worker预加载js

我们知道JavaScript是单线程的,js的加载会阻塞主线程,影响页面渲染(这句话其实表达不准确,后面会讲)。必须保证在不影响主线程的情况下,对下一级页面的js进行预加载,就必须用到多线程。于是我便想到了Web Worker。

Web Worker 为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。

可在我实现的过程中,遇到了一个棘手的问题。new Worker()参数必须是来自网络且与主线程同源,所以需要提前知道每个页面webpack打包后对应的js文件路径。也就是我需要在编写Worker代码时就要知道代码打包后的路径,并且页面每次打包生成的js文件名都有随机数的。这对我们编写和维护Web Worker文件造成了很大影响。

在我苦思如何解决这个问题时,我无意中发现了另外一个简单的js预加载方案。

import预加载页面

在Vue中,我们可以直接调用import()加载js文件或者Vue组件。但是因为我前面提到的“js的加载会阻塞主线程,影响页面渲染”,所以我一开始想到要用Web Worker多线程能力来实现。但这句话表达是不准确的。经过我试验,网络加载js文件并不会阻塞主线程,只有js代码的执行才会阻塞。为什么会有“js的加载会阻塞主线程”这个结论,我想可能是因为之前的网页大多数都是在html添加标签加载js,一般js文件加载即执行。

在Vue中,调用import('src/xxx/index.vue')只会网络请求了该Vue组件,并不会有js代码的执行,因此也并不会阻塞主线程。有了这个结论,js的预加载方案就很容易实现了。方案可以查看下面的流程图,具体代码也是比较简单的。 在这里插入图片描述

优化效果

经过上面两点优化后,页面的启动耗时和转场时间都有了很大的提升。 在这里插入图片描述 在这里插入图片描述

体验优化

H5性能优化是为了用户更快的看到页面和交互,而H5的体验优化,则是为了用户在使用过程中有爽的体验。我们知道,H5的体验一般不如原生,其中一个很大的原因是H5在交互和动效方面与原生app有很大的差距。而接下来我对H5的体验优化,整体的方向就是仿App体验。

一、加载过的页面重新展示时不用重复加载(keep-alive)

Vue是单页面应用,默认情况下回退上一页是会重新加载页面的,这大大影响了页面间跳转体验。不过Vue提供了keep-alive模式,可以让控制任意组件在router-view中不被销毁,可以实现原生App那种丝滑回退的感觉。实现keep-alive一般有两种方式:

1. include exclude

可以在router-view中添加include或者exclude属性,设置哪些组件需要keep-alive。参数是组件的name。

include: 字符串或正则表达式。只有匹配的组件会被缓存。exclude: 字符串或正则表达式。任何匹配的组件都不会被缓存。 2. 不同的router-view

使用$route.meta的keepAlive属性:

需要在router中设置router的meta:

routes: [ { path: '/', name: 'Index', component: Index, meta: { keepAlive: true // 需要缓存 } }, { path: '/page1', name: 'Page1', component: Page1, meta: { keepAlive: false // 不需要被缓存 } } ]

实现后Vue生命周期方法会回调activated和deactivated:

activated:Vue组件处于前台时会回调该方法。可以做数据的处理。deactivated:Vue组件立刻前台时回回调该方法。可做一些资源是释放。

实现效果:

优化前: 在这里插入图片描述

优化后: 在这里插入图片描述

二、列表滚动位置记录

H5另外一个体验不好的地方,点击列表跳转后,回退到上一级页面,并不会记录滚动的位置。不过,页面实现了keep-alive后,要想实现列表滚动位置记录就比较简单了。

可以在router.afterEach()时把页面滑动距离存在meta中,然后页面activated时取出之前存的滑动距离重新设置上去。

function afterEachCb(to, from) { const keepPositionWrap = document.querySelector('.keep-position-wrap'); if (!from.meta || !from.meta.keepPosition) { return; } if (keepPositionWrap) { const { scrollTop } = keepPositionWrap; from.meta.$scrollTop = scrollTop; } } activated() { const keepPositionWrap = document.querySelector('.keep-position-wrap'); if (!this.$route || !this.$route.meta || !this.$route.meta.keepPosition) { return; } if (keepPositionWrap && this.$route.meta.$scrollTop && typeof keepPositionWrap.scrollTo === 'function' ) { keepPositionWrap.scrollTo(0, this.$route.meta.$scrollTop); } }

优化前: 在这里插入图片描述

优化后: 在这里插入图片描述

三、页面转场动画

原生App页面间的转场是有切换动画的,让用户在页面间跳转显得更顺畅和自然。那H5是否也能实现这种效果呢? 于是我查找方案时,留意到GitHub上有一个Star比较多的库,能在Vue中很好的实现页面间的转场动画。Vueg----page-transition-plugin,具体使用和原理,有兴趣可以直接去Github查看。接入后,效果如下:

优化前:

在这里插入图片描述

优化后:

在这里插入图片描述

以上,是我对H5的性能优化与体验优化总结。 END



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有