从负一步开始的前端性能优化

1,646 阅读3分钟

两年前,我曾经写了一篇关于性能优化的文章, 在里面提出性能优化要先对页面性能进行记录,而且要按照页面访问的整个流程分步骤进行优化。

两年过去了,我又有了一点新的思考,在阿里也学习到了一些新的优化方法,在这里分享给大家。

关于性能优化的时机,其实可以更早,比用户输入url更早,即用户将要访问你的页面这一步开始优化。

因此,我们可以将性能优化按时间顺序分为三块:

页面访问前,页面加载中,页面运行时

用户访问网站前的性能优化

  • 推送资源:
    • 预先将页面资源如JS,图片,多媒体文件推送到客户端/浏览器
  • 预加载:
    • prefetch(可能使用的资源)
    • preload(必要资源)
    • prerender
  • 提前打开webview容器:
    • 打开webview容器需要一些时间,我们可以提前打开webview来省去这些时间
  • 预先请求AJAX:
    • 提前获取下个跳转页面需要的ajax数据,缓存到localstorage

页面加载过程中的性能优化

  • 查询强缓存:

    • service worker
    • 强缓存
  • 解析dns:

    • 域名收敛
    • http dns
    • dns-prefetch: <link rel="dns-prefetch" href="/domain.com'>
    • 使用CDN,将图片等资源的dns配置指向cdn,加速下载,抹平运营商差异
  • 建立tcp链接:

    • http2: 多路复用
    • keep alive: 长连接
    • 域名发散: 突破并发请求限制
    • 雪碧图
    • 打包代码
  • 发送请求;

    • disk cache协商缓存
    • 小图片使用base64免去请求。
  • 服务器处理请求:

    • 少一些重定向, 301永久,302临时
    • 使用hsts强制https,307
  • 发送响应:

    • gzip压缩资源
    • 用更好的格式如webp
    • 使用<script type=module>传输es6版本的代码, <script nomodule>传输es5代码
  • 解析html:

    • js在下避免阻塞,
    • defer有序,文档解析完成后才执行。 async加载后立刻执行,乱序
  • 构建渲染树:

    • 减少DOM的数量和嵌套层级
    • 减少重绘重排: 减少dom操作,减少读取几何布局属性,class代替sttyle,resize,scroll时节流防抖。
    • 懒加载
    • css优化:减少选择器
  • 白屏:

    • 骨架屏
    • 服务器渲染
  • 运行JS:

    • 依赖版本统一
    • 精简代码
    • tree shaking
    • 代码分割
  • 获取渲染需要的接口:

    • localstorage缓存时效性不强的数据
    • 在用户打开页面的过程中就获取接口(需要客户端配合改造,可以使用url带参数或是配置文件)
  • 首屏内容:

    • placeholder
    • 关键css和dom
  • 页面可交互 DOMContentloaded

  • 加载完成 load

页面运行时的性能优化

使用raf记录fps可以记录帧率

  • 构建合成层启用GPU加速:
    • will change: opacity、transform、top left bottom right
    • transfrom:translateZ
    • position:fixed
    • zIndex
  • 减少重绘重排
    • 避免频繁操作样式和DOM
    • 避免读取offsettop,scrolltop,clienttop等属性
    • class代替style
    • 批量修改的元素、复杂动画脱离文档流
  • 虚拟滚动条应对无限加载
  • 节流防抖
  • 虚拟DOM
  • 用raf来做动画
  • 滚动优化
    • 节点回收
    • 占位
    • 事件节流,事件代理
  • 对性能较差的机型降级:(怎么判断?)
    • 使用canvas嗅探GPU型号:关键词包括experimental-webgl、WEBGL_debug_renderer_info、info.UNMASKED_RENDERER_WEBGL
    • Native API手机机型识别
    • UA 获取系统版本
    • 分辨率

如果我的文章对你有帮助,欢迎 star和关注我的github~