前端性能优化导向地图

前端性能优化

文章是自己导出的,没有做优先级,请配合 mindmap 食用

前端性能优化导向地图

浏览器缓存

Memory Cache

  • 内存中的缓存,优先级上,是浏览器最先开始尝试命中的一种缓存

  • 与渲染进程并存,当进程结束,内存缓存也会消失

  • 内存划分规则没有定论,且存放位置有随机性,浏览器秉承内存节约原则,大文件一般都直接进磁盘

    • Base64 格式图片几乎永远可以进 Memory Cache
    • 体积不大的 js、css 文件有较大几率被写入,大一点就直接进磁盘

Service Worker Cache

  • 脱离于浏览器,无法直接访问 DOM
  • 使用场景和具体案例有哪些

HTTP Cache

  • 强缓存

    • 优先级高,在命中失败的情况下,才走协商缓存

    • 特征

      • expires

        • 有可能服务器和客户端有时间差,导致意料之外的结果
      • cache-control

        • max-age 与 expires 我们普遍优先 max-age

        • s-maxage 优先与 max-age

          • s-maxage 仅在代理服务器中生效,客户端中我们只考虑 max-age
    • no-store 与 no-cache

      • no-cache:绕开了浏览器,每次请求都不会询问浏览器缓存,直接向服务端去确认资源是否过期,即走协商缓存的路线

        • 浏览器缓存、向服务端确认是否过期、服务端发送请求的区别?
      • no-store:不实用任何缓存策略,指允许向服务端发送请求

    • 什么资源适合走强缓存

  • 协商缓存

    • Last-Modified

      • 定义

        • 依赖与服务端与浏览器之间你的通信,浏览器向服务器询问缓存的相关信息,判断是否重新发起请求、下载完整响应,还是从本地获取缓存资源.如果服务端提示资源没有改动,则会被重定向到浏览器缓存,此时网络请求是 304
      • 过程

        • 每次请求会带上 If-Modified-Since 时间戳子都拿,他的值是上一次 response 返回给他的 last-modified,服务器接收到这个时间戳后,与资源在服务器上的最后修改时间进行比较,如果发生变化则发生完整响应,否则返回 304 响应
      • 弊端

        • 如果服务器没有正确感知文件的变化,则可能会出错

          • 例子 🌰

            • 我们编辑了文件,但文件的内容没有改变。服务端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应——不该重新请求的时候,也会重新请求。
            • 当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的——该重新请求的时候,反而没有重新请求了。
    • Etag

      • Etag 是由服务器为每个资源生成的唯一的标识字符串

      • 与 Last-Modified 类似,优先级高于 Last-Modified

        • ETag: W/“2a3b-1602480f459”
        • If-None-Match: W/“2a3b-1602480f459”
      • Etag 的生成需要服务器额外开销,影戏服务端性能,是 Last-Modified 的补充和强化

  • Floating Topic

  • 流程图

Push Cache (拓展)

  • HTTP2 新特性,比较新颖,处于萌芽阶段
  • Push Cache 是缓存的最后一道防线。浏览器只有在 Memory Cache、HTTP Cache 和 Service Worker Cache 均未命中的情况下才会去询问 Push Cache。
  • Push Cache 是一种存在于会话阶段的缓存,当 session 终止时,缓存也随之释放
  • 不同的页面只要共享了同一个 HTTP2 连接,那么它们就可以共享同一个 Push Cache
  • 深入可看:https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

本地缓存

几种缓存类型

  • Cookie

    - 特点:文本文件,运送客户端状态
    - 4kb上限,存在不必要对Cookie传输开销(例如图片)
    

    解决办法: 使用不同域名 CDN 加载资源

  • Web Storage

    • LocalStorage

      • 存储内容稳定的资源,例如不变的图片 base64,不经常更新的 css、js 等
    • SessionStorage

      • 存储会话级别的信息
  • indexedDB

    • 使用场景

      • 账号密码填写记录
      • 长久不变的数据
      • 一些日志,等空闲时间打包回传
      • 键值对较多的情况,不必字符串化
      • Service Workers 中开发应用,只能选 indexedDB
    • 第三方:Dexie.js

    • 替代方案

      • 如果觉得 indexedDB 学习曲线比较陡峭,可以选择替代方案,localforage.localforage 的逻辑是这样的:优先使用 IndexedDB 存储数据,如果浏览器不支持,使用 WebSQL,浏览器再不支持,使用 localStorage,语法与 localStorage 相同,唯一的不同是 localforage 是异步的
      • https://github.com/localForage/localForage

拓展

DOM 优化

回流 Reflow/重排

  • 修改几何属性

  • 改变 DOM 树结构,即节点的增删移动

  • 即时计算的属性(offsetTop、getComputedStyle 等)

  • 思路

    • 通过变量存储属性值,避免频繁改动
    • 避免逐条改变样式,使用类名去合并样式
    • DOM 离线,适合操作频繁的情况

重绘 Repaint

重排一定会重绘,重绘不一定重排

思路

  • 减少 DOM 操作

    • 最佳实践:DOM Fragment
  • DOM 更新包装成 micro 任务,可以减少一次无用 render

Webpack 性能调优

两个瓶颈

  • Webpack 构建过程时间久
  • Webpack 打包结果体积大

优化方案

  • 不要让 loader 做太多事

    - 善用include/exclude
    - 开启缓存,将转译结果缓存至文件系统,
    

    提升 babel-loader 工作效率 2 倍
    loader: ‘babel-loader?cacheDirectory=true’

  • 不要放过第三方库

    • Externals、CommonsChunkPlugin 不是最好的选择,DllPlugin 会比较不错
  • 将 loader 由单进程转为多进程

    • HappyPack
    • parallel
  • 构建结果体积压缩

    • webpack-bundle-analyzer
  • 删除冗余代码

    • Tree-Shaking

      • 更适合用来处理模块级别的冗余代码。至于粒度更细的冗余代码的去除,往往会被整合进 JS 或 CSS 的压缩或分离过程中
    • UglifyJsPlugin

      • webpack4 已经默认使用, 通过配置 optimization.minimize 与 optimization.minimizer 来自定义压缩相关的操作
  • 按需加载

    • 核心是:require.ensure(dependencies, callback, chunkName)
    • 这是一个异步方法,在跳转到目标路由到时候,异步方法的回调才会生效,真正获取目标路由下的 Content

杂项

多图页面,懒加载

防抖、节流

visibilityChange

服务端渲染

  • 先理解客户端渲染,页面通过 js 运行出来,挂载到 root 下进行渲染的方式
  • 服务端渲染:所见即所得,页面呈现的内容在 html 源文件中可以找到
  • 优点: 对 seo 有正向效应,解决了首屏加载过慢的问题
  • 客户端通常数量远超于服务端数量,除非是对性能要求很高,否则一般不会太刻意要求服务端渲染来提升性能

CSS、JS

  • CSS 书写经验总结

    • #myList li{} ,浏览器从右开始匹配,会增大开销
    • 减少嵌套,减少后代选择器
  • 加载顺序,JS 优先 CSS,两者一般都会阻塞 DOM 渲染

性能监测与评估

Performance

LightHouse

性能上报方案

  • Performance API,拿到性能数据进行二次处理

图片优化

图片类型

  • JPG/JPEG

    • 关键字: 有损压缩、体积小、加载快、不支持透明
    • 适用于呈现色彩丰富的图片,日常开发中,经常作为大的背景图、轮播图或 banner 图出现(例如旧版京东、淘宝)
  • PNG

    • 关键字: 无损压缩、质量高、体积大、支持透明
    • 比 JPG 更强的色彩表现力,优化了 JPG 的局限,但是体积大
    • 适用于小的 Logo、颜色简单且对比强烈的图片或背景等
  • SVG

    • 关键字: 文本文件、体积小、不失真、兼容性好
    • 相较 PNG、JPG,体积更小,可压缩性更强,图片无限放大不失真
    • 缺点是渲染成本高,其次是如果要编程的话,需要学习成本
  • Base64

    - 关键字: 文本文件、依赖编码、小图标解决方案
    - 图片base64编码后,通常会膨胀为原文件的4/3
    - 适用于: 图片实际尺寸很小,4kb以下
    

    无法以雪碧图的形式于其他小图结合
    图片更新频率非常低的情况

  • Webp

    - 关键字: 年轻的全能型选手、
    

    支持透明、支持动图 - 与 PNG 相比,无损图像缩小了 26%
    有损图像比同类 JPEG 小 25-34% - 缺陷:兼容性,不过目前态势比较好
    开发时需要准备降级方案

Tips

  • 如果借用第三方转换图片格式,需要考虑数据持久化,例如七牛云中自动转格式,时间就会自动清除缓存,造成二次资源获取,反而翻车
  • 如果是较小图片,纯色的话,可以建议换成 iconfont 会更为合适

HTTP 压缩

Gzip

  • 压缩和解压的时间,相对传输过程中节省的时间开销,微不足道
  • 高效,压缩后通常能帮我们减少响应 70% 左右的大小,但并不保证针对每一个文件的压缩都会使其变小
  • 服务器端的 Gzip 与 webpack 的 Gzip 并不能互相替代,许哟啊结合业务实际强度以及资源权衡

CDN 缓存

目的: 提升请求响应能力

两个核心

  • 缓存
  • 回源

感谢阅读,勘误、纠错或其他请联系progerchai@gmail.com,或者点击这里提 issue 给我
欢迎交流 👏,你的每一次指导都可以让我进步


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!