Web性能优化

81 阅读5分钟

网络优化

  • DNS预解析

    借助HTML提供的<link ref="dns-prefetch" href="xxx" />标签,可以对可能访问的其他源的域名进行前置的DNS解析。但需要注意的是href填写的内容应该是跨源的,因为当浏览器看到这个link标签时,你的文档已经被下载并开始执行了。也可以配合preconnect进一步结合,preconnect是预链接,还包含了三次TCP握手,或者https的TLS握手,但是需要注意的是preconnect最好只针对关键链接,而非所有,否则适得其反。

  • 缓存

    从缓存中快速获取数据,减轻服务器压力,主要有以下两种

    • 强制缓存:主要依赖于header中的Expire(Http1.0)Catch-Control字段的max-age,判断当前缓存是否过期,Expire是过期时间,max-age是相对过期时间
    • 协商缓存:主要依赖E-TagLast-Modified两个字段实现,浏览器在请求一个资源时向浏览器发送一个请求,携带上这两个字段,服务器通过这两个字段判断缓存是否有效,有效则返回一个304的状态码,并且不带相应报文,浏览器从缓存拿取资源。否则返回新的E-TagLast-Modified,以及相应报文。详细请戳这里
  • CDN(内容分发)

    内容分发是一组分散在不同地理位置的服务器,上传到云上的资源会被同步到各个CDN节点,浏览器在请求资源时会到最近的相应最快的节点拉取资源。

  • 响应内容压缩

    浏览器通过请求头的Accept-Encoding列出压缩方法,例如gzip,deflate,br,服务器收到请求后,采用浏览器告知的一种压缩方法对相应内容进行压缩,并将这种方法写入到响应头的Content-Encoding

    图片.png 图片.png

  • 使用多域名

    现代浏览器,对同一域名的请求,都限制有并发数,所以可以合理规划你的资源域名(太多了会导致DNS等其他损耗,保持在2-4个就好),通常可以将静态资源和接口分开,甚至对静态资源的图片、js、css等进行合理划分。

  • 使用雪碧图

    将一些小图做在一张大图上,既可以减少请求次数,也可以提前加载图片。

  • 启用HTTP2.0

    HTTP2.0提供了头部压缩,以及多路复用的特性

    • 头部压缩:http1时代会提供一些压缩算法对请求体响应体进行压缩,2.0对头部也会进行压缩。而且同一个网站中的请求拥有很多相同的header内容,只有少部分的是不一致的,客户端和服务器都会维护一份header的哈希表,每次请求中,相同header并不会传输真正的内容。
    • 多路复用:http2.0不再使用文本传输,避免了转义的损耗。采用二进制数据传输,在同一个TCP管道中对请求进行分片,把一个请求拆分成多个请求多个数据包,最终完成拼接。详细请戳

渲染优化

浏览器的渲染流程是根据css构建CSSOM树和DOM树,最终合成一棵渲染树,根据渲染树做布局(回流)绘制(重绘)

  • 避免CSS阻塞

    CSS会影响渲染树的构建,阻塞页面渲染,所以需要早快的加载CSS资源,将CSS放在Head里

  • 避免JS阻塞

    众所周知,浏览器是单线程的,在js执行时,页面停止渲染的。而且每一帧的流程也是对js执行、页面渲染做好妥帖安排的,如图一个完整的帧流程:处理用户输入-》JS执行-》RAF-》解析HTML计算样式布局-》更新渲染树绘制-》RIC。所以要尽可能的减少JS的阻塞,可以利用defer:并行加载,文档加载完成执行async:并行加载并执行。当然尽可能将js块放在body的最后边。 图片.png

  • 首屏加载优化

    • 使用骨架屏,降低用户在等待时间白屏带来的焦躁感
    • 资源按需加载,首页不需要的延迟加载
  • 减少回流和重绘

    • 对多个节点的处理,使用documentFragment
    • translate替代top,visibility替代display,opacity替代visibility,因为top位置和display等的变化会导致回流,visibility会引起重绘
    • 不要在循环里反复获取设置DOM节点的样式属性
    • DOM读写分离,浏览器具有惰性渲染机制,多次修改DOM可能只触发浏览器的一次渲染。而如果修改DOM后,立即读取DOM。为了保证读取到正确的DOM值,会触发浏览器的一次渲染。因此,修改DOM的操作要与访问DOM分开进行
    • 少用table,table的每一个单元格变化都会引起整个table的回流重绘

JS的性能优化

  • 事件委托,降低事件绑定开销;子组件天然继承父组件事件
  • 防抖节流
  • 尽量不要用JS动画,CSS3的动画或者Canvas是更好的选择
  • 利用WebWorker多线程能力,避免复杂计算影响浏览器主线程

打包优化

可以利用一些第三方的打包分析库,对打包产物进行分析,了解哪些可以排除,哪些可以分割。

  • 代码分离,通过chunk配置,合理分割生成的打包产物,不要只生成一个庞大的index.js文件,也不要生成太多的需要首屏加载的资源文件
  • 公共模块抽离,采用cdn加载,而非打包到自己的打包产物中
  • 按需加载,合理利用treeShaking,将不需要的模块排除掉
  • 合理利用第三方库对打包产物进行压缩