性能优化原因:
性能问题无外乎两方面原因:渲染速度慢、请求时间长。
HTML方式解决性能渲染速度慢问题:
-
script 标签:调整加载顺序提升渲染速度
-
async 属性。立即请求文件,但不阻塞渲染引擎,而是文件加载完毕后阻塞渲染引擎并立即执行文件内容。
-
defer 属性。立即请求文件,但不阻塞渲染引擎,等到解析完 HTML 之后再执行文件内容。
-
HTML5 标准 type 属性,对应值为“module”。让浏览器按照 ECMA Script 6 标准将文件当作模块进行解析,默认阻塞效果同 defer,也可以配合 async 在请求完成后立即执行。
构建工具会把编译好的引用 JavaScript 代码的 script 标签放入到 body 标签底部。因为当渲染引擎执行到 body 底部时会先将已解析的内容渲染出来,然后再去请求相应的 JavaScript 文件。
-
-
link 标签:通过预处理提升渲染速度
-
preconnect。让浏览器在一个 HTTP 请求正式发给服务器前预先执行一些操作,这包括 DNS 解析、TLS 协商、TCP 握手,通过消除往返延迟来为用户节省时间。
-
prefetch/preload。两个值都是让浏览器预先下载并缓存某个资源,但不同的是,prefetch 可能会在浏览器忙时被忽略,而 preload 则是一定会被预先下载。
-
prerender。浏览器不仅会加载资源,还会解析执行页面,进行预渲染。
-
dns-prefetch。当 link 标签的 rel 属性值为“dns-prefetch”时,浏览器会对某个域名预先进行 DNS 解析并缓存。这样,当浏览器在请求同域名资源的时候,能省去从域名查询 IP 的过程,从而减少时间损耗。
-
<link rel = "dns-prefetch" href="//img.taobao.com">
JS解决渲染慢问题:
-
尽量不要使用复杂的匹配规则和复杂的样式,从而减少渲染引擎计算样式规则生成 CSSOM 树的时间;
-
尽量减少重排和重绘影响的区域;
-
使用 CSS3 特性来实现动画效果。
-
在循环外操作元素
-
批量操作元素
-
缓存元素集合
-
防抖、节流
-
路由拆分 路由加载时才加载JS文件
内容层面
- 使用CDN
- 单域名、多域名,单域名可以减少DNS查找次数,多域名可以增加浏览器并行下载数量,这需要权衡,
- 一般同一个域下不要超过四个资源。
- 避免重定向(分场景)
- 避免404
网络层面
- 利用缓存,可以参考另一篇文章手写文件服务器,说说前后端交互
- 文件压缩(通过响应头Accept-Encoding: gzip, deflate, br告诉服务器你支持的压缩类型)
- 按需加载,提取公共代码,tree-shaking等(都可以通过webpack来实现)
- 减少cookie大小
- 文件合并,通过css雪碧图合并图片
- 文件预加载、图片懒加载
渲染层面
- js放底部,css放顶部
- 减少reflow(回流)和repaint(重绘)
- 减少dom节点
代码层面
- 缓存dom节点,减少节点查找,css选择器层级优化
- 减少dom节点操作
- 合理使用break、continue、return等,优化循环
- 像react用到的事件委托、对象池等手段