前端打工人的性能优化

491 阅读4分钟

前言

你是不是觉得一天天的代码写过去写过来都一个样,没什么新鲜感?
这样会导致你出现一种错觉,“哎,Web前端好简单呀,Vue好简单呀,React一点儿也不难”,公司安排的任务我都能完成的错觉
其实现实情况就是我们还有很多东西需要学习,需要实践,我们还差得很远哟~~~

下面是我使用过的优化方式,优先级从前到后,大家如果有其它比较nice的优化方式,让我来试试呀,么么哒

性能测试网站吧~

大胆把你的网站放进去试试吧 GOGOGO

HTTP2

http/1.1问题

  • 对于同一个域名,浏览器最多只能同时创建 6~8 个 TCP 连接 (不同浏览器不一样) 。

  • 合并文件、内联资源、雪碧图、域名分片对于 HTTP/2 来说是不必要的,使用 h2 尽可能将资源细粒化,文件分解地尽可能散,不用担心请求数多,所以h1的优化方式不是很实用哟。

  • 我们的 JD 就是使用了HTTP2的代表,所以使用HTTP2是应该是立即的

图片

  • 懒加载(Intersection Observer)
  • 压缩
  • 尽量保证图片尺寸大小正确
  • 避免空的src
  • 采用下一代格式图片WebP 兼容性最好, JD 老大哥也在使用哦

网络

  • CDN
  • 域名预解析 rel=dns-prefetch
  • 内容预加载 rel=preload or prefetch

Gzip

  • 通过request的Accept-Encoding可以判断客户端接受哪些压缩方法
  • 服务端通过Content-Encoding说明当前服务器的压缩方式
  • 前端可以通过webpack生成gz文件,这样服务器就不需要做这一步了

资源加载顺序

css加载

  • CSS会阻塞渲染树的构建,不阻塞DOM构建
  • 但是在CSSOM构建完成之前,页面不会开始渲染(一片空白)
  • js虽然会阻塞后续DOM构建,但是前面已经就绪的内容会进行渲染
  • CSS虽然不阻塞DOM构建,但是会阻塞后面js的执行,从而间接阻塞完整DOM的构建
  • 测试发现,后边的js虽然先下载下来,但是只有等css执行完毕后,才得到执行
  • 然后进一步js又会阻塞后续DOM树构建,就这样导致整个渲染过程话费更多时间。所以我们要尽快加载CSS并构建CSSOM。
  • 所以应该尽快加载css文件好生成对应的CSSOM

js加载

  • JS默认也是会阻塞DOM和渲染树的构建的
  • 声明为defer的脚本会延迟到DOM构建完成后(DOMInteractive事件),DOMContentLoaded和window.onload事件之前执行(但依然会被浏览器的预加载策略提前下载)。
  • 只针对外联脚本有效。多个defer会按照先后顺序串行执行。
  • 声明为async的脚本会异步地下载和执行,会在window.onload事件之前执行,但是可能会在DOMContenLoaded事件前后执行。
  • css和js文件会比图片有更高的优先级

通过上面就能理解为什么CSS文件放在head中,JS放在body底部了,但是一些特殊的JS还是需要放在head中的,例如babel-polyfill.js文件、flexible.js

代码优化

document.write

会阻塞页面渲染,尤其注入一段脚本就更夸张了

eval

eval 将传入的字符串当做脚本执行,会大幅度降低脚本执行性能

全局变量

全局变量的查找作用域链更长,生命周期也更长,且有内存泄漏的风险,甚至会产生不可预估的 bug 出现。项目中的第三方库一般都会暴露一些全局变量,这和你声明的全局变量也可能会发生冲突。所以,尽量谨慎地使用全局变量

循环操作优先级(从小到大)

  • for - forEach/for-of/map/filter - for-in
  • 最慢的属于 for-in,它之所以慢,是因为它常用于对象属性的遍历,并且会访问自身属性以及其原型链的属性(包括不可枚举属性)
  • 减少循环中的活动 例如把xx.length 放在for外面
  • 尽量不要在循环中声明函数

尽量少地使用闭包

  • 闭包提供了一些便捷性,但同时也会有一些性能影响,由于保留着原应被回收的变量引用,增加了作用域链的长度,影响性能。
  • 同时它会可能会有内存泄漏的风险。

判断语句if/switch

  • 当超过三个判断尽量使用switch
  • if量提前return,或者使用三元操作符

===/!==

==!= 操作符会引起 JS 的数据类型隐式转换,导致一些不可预估的负面作用,所以,更明智的选择是,总是去使用 ===!== 进行相等判断

New

通过 new 操作符新建一个对象,类似于函数调用,同时会做一些关联原型链等操作,性能会慢很多,字面量则在写法上更直观友好且高效

操作DOM

现在是个前端都知道操作DOM消耗性能,哈哈哈哈

事件绑定

能使用事件委托的都使用事件委托

Thanks