随着互联网的发展,用户对产品的体验要求越来越高,如何留住用户是关键,H5作为载体,那如何提高H5的性能就成了一门重要的工作,那如何提高H5的性能呢,我们从以下三个方面具体说一下
1、减少http请求次数和传输报文的大小
- 雪碧图
- 使用字体图标或者svg矢量图
- 减少http请求次数或者减少请求内容大小
- 渲染更快:因为他们是基于代码实现的,而位图(png/jpg/gif)需要先把图片编码再渲染
- 不会失真变形
- 图片可以使用
webp格式的,相对来说会小一点
需要服务器支持这种格式的请求处理
export default function checkWebpFormat() {
try {
return new Promise((resolve) => {
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf("webp") !== -1) {
localStorage.setItem("isSupportWebp", 1); // 通过ua判断是否支持webp
resolve(1);
} else {
// 原始方法判断
var img = new Image();
var tid = setTimeout(function () {
img.onload = img.error = null;
img = null;
}, 500);
img.onload = function () {
clearTimeout(tid);
if (img.width > 0 && img.height > 0) {
localStorage.setItem("isSupportWebp", 1);
resolve(1);
} else {
localStorage.setItem("isSupportWebp", 2);
resolve(2);
}
};
img.onerror = function () {
clearTimeout(tid);
localStorage.setItem("isSupportWebp", 2);
resolve(2);
};
img.src =
"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=";
}
});
} catch (e) {
console.log(e);
}
}
- 图片懒加载(延迟加载)
- 第一次加载页面时不去请求真实的图片,提高第一次页面渲染的速度
- 当页面加载完,把可视区域的图片做真实加载,没有在可视区域的先不加载真实图片
可节约流量,减少对服务器的请求压力
- 对于数据可以分页加载(分页技术)
- 音视频文件取消预加载
(preload='none'),默认是auto,这样可以增加第一次渲染页面的速度 - 客户端和服务器端的数据传输尽可能基于
json格式完成,xml格式化比json格式要大一些(还可以使用二进制编码或者文件流格式,这种比文件传输好很多) - 把页面中的
css/js/img等文件合并压缩 - 图片地图:对于多次调取使用的图片(尤其是背景图)我们尽可能把它提取成公共的样式,而不是每一次重新设置
background - 图片base64
用base64代表图片可以减少http请求,增加浏览器渲染速度,原理是浏览器解析图片也要先将图片转成位图后再渲染,base64减少了浏览器解析位图的过程。但是使用base64会导致代码不好维护和开发,建议少使用,现在可以在webpack里配置图片的base64
2、设置各种缓存、预处理和长连接(keep-alive)机制
- 把不经常更改的静态资源做缓存处理(一般做的是304或者Etag等协商缓存)
- DNS缓存或预处理
(dns-prefetch),减少DNS的查找 - 设置本地的离线存储
(manifest)或者把一些不经常更改的数据做本地存储(webstorage、indexDB)等 - 有钱就做CDN(地域分布式服务器)或者增加服务器
- 建立
Connection:keep-aliveTCP长连接 - 建立
Cache- Control和Expires HTTP强缓存 - 使用
http2协议(现在一般用的是http1.1)- http2与http1的区别,http2与http1的区别
- 可以多条TCP通道共存(管道化链接)
- 一个项目分为不同的域(不同的服务器)资源web服务器、数据服务器、图片服务器、音频服务器,合理利用服务器资源。但是这样会导致过多的DNS解析
3、代码方面的性能优化
- 减少闭包的使用
(因为过多的使用闭包会产生很对不好销毁的内存,处理不好的话会导致内存溢出“栈溢出”,减少闭包的嵌套(减少作用域链的查找层级)
- 死递归
- 引用类型之间的相互引用
- 对于动画来说,能用css实现的不用js
(能用
transform处理的,不用传统css,因为transform可开启硬件加速,不会引发回流,再或者使用定位的元素,因为定位元素会脱离文档流,不会对其他元素的位置造成影响),能用requestAnimationFrame解决的不用定时器requestAnmationFrame还有一个好处,当页面处于休眠无访问状态,动画会自动暂停,直到重新恢复访问,而定时器不论什么状态,动画一直存在,除非关闭页面
- 避免使用iframe
因为·iframe·会嵌入其他页面,这样父页面渲染时,还要同时把子页面也渲染了,渲染进度会变慢
- 减少直接对DOM的操作
原因是减少DOM的回流和重绘,当代项目基本上都是基于
MVVM/MVC数据驱动视图渲染的,对DOM的操作框架本身完成,性能要好很多 - 低耦合高内聚
基于封装的方式:方法封装、插件、组件、类库等封装,减少页面中的冗余代码,提高代码使用率
- 尽可能使用事件委托
- 避免出现死循环或者嵌套循环
嵌套循环会乘倍增加循环的次数
- 项目中尽可能使用异步编程来模拟出多线程的效果,避免主线程堵塞
异步操作基于promise设计模式来管理
- js中不要使用with
- 避免使用css表达式
- 函数的节流和防抖
- 减少使用eval
主要原因是防止压缩代码时,由于符号书写不合规出现代码混乱
- 减少filter滤镜的使用
- 尽可能减少选择器的层级(选择器是从右向左开始解析)
.box a {}和a{},后者的性能好 - 尽可能减少table
- 手动回收堆栈内存(每次赋值为null)