拿来即用的前端性能优化方案

123 阅读5分钟

随着互联网的发展,用户对产品的体验要求越来越高,如何留住用户是关键,H5作为载体,那如何提高H5的性能就成了一门重要的工作,那如何提高H5的性能呢,我们从以下三个方面具体说一下

1、减少http请求次数和传输报文的大小

  1. 雪碧图
  2. 使用字体图标或者svg矢量图
    1. 减少http请求次数或者减少请求内容大小
    2. 渲染更快:因为他们是基于代码实现的,而位图(png/jpg/gif)需要先把图片编码再渲染
    3. 不会失真变形
    4. 图片可以使用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);
	}
}
 
  1. 图片懒加载(延迟加载)
    1. 第一次加载页面时不去请求真实的图片,提高第一次页面渲染的速度
    2. 当页面加载完,把可视区域的图片做真实加载,没有在可视区域的先不加载真实图片

      可节约流量,减少对服务器的请求压力

    3. 对于数据可以分页加载(分页技术)
  2. 音视频文件取消预加载(preload='none'),默认是auto,这样可以增加第一次渲染页面的速度
  3. 客户端和服务器端的数据传输尽可能基于json格式完成,xml格式化比json格式要大一些(还可以使用二进制编码或者文件流格式,这种比文件传输好很多)
  4. 把页面中的css/js/img等文件合并压缩
    1. 合并:争取把css和js都只导入一个(webpack可以实现自动合并压缩)对webpack感兴趣的可直击进webpack官网
    2. 压缩:基于webpack可以压缩,图片可找在线压缩工具(熊猫压缩),还可以使用服务器端的gzip压缩
  5. 图片地图:对于多次调取使用的图片(尤其是背景图)我们尽可能把它提取成公共的样式,而不是每一次重新设置background
  6. 图片base64

    用base64代表图片可以减少http请求,增加浏览器渲染速度,原理是浏览器解析图片也要先将图片转成位图后再渲染,base64减少了浏览器解析位图的过程。但是使用base64会导致代码不好维护和开发,建议少使用,现在可以在webpack里配置图片的base64

2、设置各种缓存、预处理和长连接(keep-alive)机制

  1. 把不经常更改的静态资源做缓存处理(一般做的是304或者Etag等协商缓存)
  2. DNS缓存或预处理(dns-prefetch),减少DNS的查找
  3. 设置本地的离线存储(manifest)或者把一些不经常更改的数据做本地存储(webstorage、indexDB)
  4. 有钱就做CDN(地域分布式服务器)或者增加服务器
  5. 建立Connection:keep-aliveTCP长连接
  6. 建立Cache- Control Expires HTTP强缓存
  7. 使用http2协议(现在一般用的是http1.1
    1. http2与http1的区别,http2与http1的区别
    2. 可以多条TCP通道共存(管道化链接)
  8. 一个项目分为不同的域(不同的服务器)资源web服务器、数据服务器、图片服务器、音频服务器,合理利用服务器资源。但是这样会导致过多的DNS解析

3、代码方面的性能优化

  1. 减少闭包的使用

    (因为过多的使用闭包会产生很对不好销毁的内存,处理不好的话会导致内存溢出“栈溢出”,减少闭包的嵌套(减少作用域链的查找层级)

    1. 死递归
    2. 引用类型之间的相互引用
  2. 对于动画来说,能用css实现的不用js

    (能用transform处理的,不用传统css,因为transform可开启硬件加速,不会引发回流,再或者使用定位的元素,因为定位元素会脱离文档流,不会对其他元素的位置造成影响),能用requestAnimationFrame解决的不用定时器

    1. requestAnmationFrame还有一个好处,当页面处于休眠无访问状态,动画会自动暂停,直到重新恢复访问,而定时器不论什么状态,动画一直存在,除非关闭页面
  3. 避免使用iframe

    因为·iframe·会嵌入其他页面,这样父页面渲染时,还要同时把子页面也渲染了,渲染进度会变慢

  4. 减少直接对DOM的操作

    原因是减少DOM的回流和重绘,当代项目基本上都是基于MVVM/MVC数据驱动视图渲染的,对DOM的操作框架本身完成,性能要好很多

  5. 低耦合高内聚

    基于封装的方式:方法封装、插件、组件、类库等封装,减少页面中的冗余代码,提高代码使用率

  6. 尽可能使用事件委托
  7. 避免出现死循环或者嵌套循环

    嵌套循环会乘倍增加循环的次数

  8. 项目中尽可能使用异步编程来模拟出多线程的效果,避免主线程堵塞

    异步操作基于promise设计模式来管理

  9. js中不要使用with
  10. 避免使用css表达式
  11. 函数的节流和防抖
  12. 减少使用eval

    主要原因是防止压缩代码时,由于符号书写不合规出现代码混乱

  13. 减少filter滤镜的使用
  14. 尽可能减少选择器的层级(选择器是从右向左开始解析).box a {}a{},后者的性能好
  15. 尽可能减少table
  16. 手动回收堆栈内存(每次赋值为null)