前端优化之JS的开销与如何缩短解析时间
相同大小的JS代码和一个图片文件的加载,JS文件是比图片的加载要慢很多的。因为JS代码有一个编译和解析的过程。图片的解码与绘制是很快的。
js的加载过程可能会造成阻塞,此时即使用户看到了页面,但是却无法进行交互。
1.如何从代码层面上进行优化:
- 外部第三方的JS文件:
- Code splitting 代码拆分,按需加载
- Tree shaking 代码减重 (摇树,摇掉枯萎的叶子)
- 减少主线程工作量:
- 避免长任务
- 避免超过1KB的行间脚本
- 使用rAF和rIC进行时间调度
如:当两个不同类型的数据进行运算时,浏览器会有一个优化的过程,会增加时间
V8的优化机制:
- 脚本流
- 字节码缓存
- 懒解析
2.函数优化
V8这样的JS引擎,默认对函数进行懒解析(lazy parsing):只有当这个函数真正被调用的时候,才会去解析函数体。这样的解析方式会对性能有很好的提升。但是实际开发中有的情况需要JS立即去执行,此时如果是懒解析的函数但是发现需要立即执行,于是又快速的进行了一个饥饿解析(eager parsing),这样的话会先进行了一次饥饿解析,然后又进行了一次懒解析,执行效率反而降低了。
那么如何告诉解析器某个函数需要立即解析:
只需加一对括号:
const add = ((a,b) => a+b) // 这样的作用是告诉解析器,当看到这个函数的时候就对这个函数进行解析 const n1 = 1 const n2 = 2 add(n1,n2)
这样当后面需要调用的时候就可以直接调用了
有个问题:
- 当把代码进行压缩时(uglyfy),可能会把这对括号去掉
- 解决:Optimize.js。可以在压缩以后把括号加回来
- uglyfy后来把这些问题也解决了,需要兼顾老版本的可以添加
3.对象优化
js是一个弱类型的语言,在声明的时候不会声明这个变量的类型。但是对于编辑器而言,还是需要一个具体的类型。如何做:在解析的时候会给这个变量赋一个具体的类型(21种隐藏类型)
对象优化可以做的事:
- 以相同顺序初始化对象成员,避免隐藏类的调整
- 实例化后避免添加新属性
- 尽量使用Array代替array-like对象(如argument)
- 避免读取超过数组的长度
- 会造成沿原型链的查找,会增加开销(据统计会相差六倍)
- 避免元素类型转换,如[1,2,3]push了一个1.2的元素,数组默认的类型会被更改
- 即类型给的越具体,编译器能做的优化越多
- 越通用,能做的优化越少
4.HTML的优化
HTML的大小占比较小,但是也能做:
- 减少iframes的使用。iframes会阻塞父文档的加载。要用的话可以使用延迟加载
- 压缩空白符
- 避免节点深层级嵌套
- 避免使用table布局
- 删除注释
- CSS&JS尽量外链
- 删除元素默认属性
借助工具:
- html-minifier
- ...
5.CSS的优化
- 降低CSS对渲染的阻塞
- 对目前用不到的CSS,可以延迟加载
- 利用GPU进行完成动画
- 使用contain属性
- 使用font-display属性
6.资源的压缩与合并
(1)为什么要压缩&合并
- 减少http请求数量
- 减少请求资源的大小
(2)HTML压缩:
- 使用在线工具进行压缩
- 使用html-minifier等npm工具
(3)CSS压缩
(4)JS压缩
- 在线JS压缩
- 使用webpack在构建时压缩
7.图片资源优化
(1)图片优化的方案
(2)图片格式的比较
- jpg:有损的压缩,压缩比高且色彩还能保持的很好。web常用
- 压缩工具imagemin,可以对jpg图片进行进一步的压缩
- 缺点:压缩比较高,可能有锯齿和边缘(logo一般不用)
- png:
- 优点:
- 可以做透明背景的图片
- 对jpg的一些缺点进行弥补
- 体积较jpg大
- 常用来做小的图标
- 压缩png:imagequant
- 优点:
- webp:
- 有很多webp转换工具
- 问题:可能有兼容性问题
- 说明:普通网站上面三种都差别不大,主要体现在大小的区别
(3)图片加载优化
① 图片的懒加载
- 原生的懒加载方案
-
<img loading=“lazy” src="xxx.jpg">
- 自定义和可扩展性不是特别好
- 需要浏览器支持
-
- 第三方图片懒加载方案
- verlok/lazyload
- yall.js
- Blazy
未完。。
8.字体的优化
(1)字体的问题:
字体未下载完成时 ,浏览器隐藏或者自动降级