一些基础细致的性能优化技巧

本文只是记录学习过程中的一些性能优化小技巧,并不全面,用于记录和为后续更加完整的优化整合做准备

图片

图片格式选择

JPEG

非常适合: 颜色丰富的照片,彩色图大焦点图、通栏 banner 图,结构不规则的图形

不适合:线条图形和文字、图标图形,因为它的压缩算法不太适合这些类型的图形,并且不支持透明度

压缩工具:jpegtran

PNG

非常适合: 纯色、透明、线条绘图、图标;边缘清晰、有大块相同颜色区域;颜色数较少单需要半透明

不适合:由于是无损存储,彩色图像体积太大,所以不太适合颜色丰富,彩色大图

压缩工具: node-pngquant-native

GIF

非常适合:动画,图标

不适合:每个像素只有 8 比特,不适合存储彩色图片

压缩工具:Gifsicle

Webp

非常适合:适用于图形和半透明图像

不适合: 最多处理 256 色,不适合彩色图片

真的需要图片吗

Web font 代替图片

使用 Data URI 代替图片

采用 Image spriting(雪碧图)

精简 HTML 代码

  • 减少 HTML 的嵌套
  • 减少 DOM 节点数
  • 减少无语义的代码(比如:<div class="clear"></div>
  • 删除 http 或者 https,如果 URL 的协议头和当前页面的协议头是一致的,或者此 URL 在多个协议都是可用的,则可以考虑删除协议头
  • 删除多余的空格、换行符、缩进和不必要的注释
  • 省略冗余标签和属性
  • 使用相对路径的 URL
  • 文件放在合适的位(CSS 放头部,JS 放底部)

CSS

提升 CSS 渲染性能

  • 谨慎使用 expensive 昂贵的属性
    • 如 :nth-child 伪类; position: fixed 定位
  • 尽量减少样式层级数量
    • 如 div ul li span i {color: true;}
  • 尽量避免使用占用过多 CPU 和内存的属性
    • 如 text-indent: -9999px
  • 尽量避免使用耗电量大的属性
    • 如 CSS3:3D transforms、CSS3 transitions、Opacity
  • 尽量避免使用 CSS 表达式
    • background-color: expression((new Date()).getHours() % 2 ? “#FFF” : “#000”)
  • 尽量避免使用通配选择器,有选择地使用选择器
    • body > a {font-weight: blod;}
  • 尽量避免类正则的属性选择器
    • *=,|=,^=,$=
  • 使用 contain 属性,告诉浏览器某些方面可以这样优化,哪些不能优化
  • 使用 font-display 属性,帮助我们把文字更早显示在页面上,还可以减少文字闪动问题

提升 CSS 文件加载性能

  • 内联首屏关键CSS(Critical CSS)
  • 使用外链的 CSS
  • 尽量避免使用 @import
  • 异步加载CSS

精简 CSS 代码

  • 使用后缩写语句
  • 删除不必要的零
  • 删除不必要的单位,如px
  • 删除过多的分号
  • 删除空格的注释
  • 尽量减少样式表的大小

合理使用 Web Fonts

  • 将字体部署在 CDN 上
  • 将字体以 base64 形式保存在 CSS 中并通过 localStorage 进行缓存
  • Google 字体库因为某些不可抗原因,应该使用国内托管服务

CSS 动画优化

  • 尽量避免同时动画
  • 延迟动画初始化
  • 结合 SVG

js

JS 优化原则

  • 当需要时才优化
  • 考虑可维护性

提升 JS 文件加载性能

  • 加载元素顺序 CSS 放在 head 头里,JS 放在 body 里

JS 遍历和函数优化

  • 尽量使用 id 选择器
  • 尽量避免使用 eval
  • JS 函数尽可能保持简洁
  • 使用事件防抖和节流函数
  • 使用事件委托

JS 动画优化

  • 避免添加大量 JS 动画
  • 尽量使用 CSS3 动画
  • 尽量使用 Canvas 动画
  • 合理使用 requestAnimationFrame 动画代替 setTimeout、setInterval
    • requestAnimationFrame 可以保证在正确的时间进行渲染,setTimeout、setInterval 无法保证 callback 回调函数执行时机

合理使用缓存

  • 合理缓存 DOM 对象
  • 缓存列表长度
  • 使用可缓存的 Ajax

使用浏览器存储对 JS 进行缓存优化

Cookie:

  • 会话管理:登录名,购物车商品,游戏得分或服务器应要记录的其它任何内容
  • 个性化:用户首选项,主题或其它设置
  • 跟踪:记录和分析用户行为,比如埋点

sessionStorage

  • 页面应用之间的传值

LocalStorage

  • 缓存静态文件内容 JS/CSS
  • 缓存不常变更的 API 接口数据
  • 存储地理位置信息
  • 浏览在页面的具体位置

IndexedDB

  • 客户端存储大量结构化数据
  • 没有网络连接的情况下使用
  • 将冗余、很少修改、单经常访问的数据,以避免随时从服务器获取数据

减少回流和重绘

CSS 方面:

  • 避免过多样式嵌套
  • 避免使用 CSS 表达式
  • 使用绝对定位,可以让动画元素脱离文档流
  • 避免使用 table 布局
  • 尽量不使用 float 布局
  • 图片最好设置 width 和 height
  • 尽量简化浏览器不必要的任务,减少页面重新布局
  • 使用 Viewport 设置屏幕缩放级别
  • 避免频繁设置样式,最好把新的 style 属性设置完成后,进行一次性更改
  • 避免使用引起回流/重绘的属性,最好把相应的变量缓存起来

JS 方面:

  • 最小化回流和重排
    • 为了减少回流和重排发生的次数,避免频繁操作 DOM,可以合并多次对 DOM 的修改,然后一次性批量处理(例如使用 createDocumentFragment)
  • 控制绘制过程和绘制区域
    • 绘制过程开销比较大的属性设置应该尽量避免使用
    • 减少绘制区域范围

DOM 编程优化

控制 DOM 大小

  • 合理的业务逻辑
  • 延迟加载即将呈现的内容

简化 DOM 操作

  • 对 DOM 节点的操作统一处理后,再插入到 DOM Tree 中
  • 可以使用 Fragment,尽量不在页面 DOM Tree 里直接操作
  • 流行框架都采用虚拟 DOM 技术,通过 diff 算法简化和减少 DOM 操作

页面加载策略

  • 懒加载(延迟加载)
    • 可以减少当前屏无效资源的加载
  • 预加载
    • 减少用户后续加载资源等待时间
    • 实现方式: 使用 Image 对象,img标签先隐藏,使用 preload(强制),prefetch(交给浏览器空闲加载)和 preconnect(链接),dns-prefetch(链接)
  • 预渲染
    • 减少用户等待时间
    • 实现方式:prerender
  • 按需加载
  • 楼层式加载

接口优化

接口服务器调用优化

  1. 接口合并
    • 这个是指一个页面的众多的业务接口和依赖的第三方接口统一使一个部署在集群的接口统一调用,以减少页面接口请求数量
  2. 接口上 CDN
    • 主要基于接口性能考虑,我们可以把不需要实时更新的接口同步至 CDN,等此接口内容变更之后自动同步至 CDN 集群上。如果一定时间内容未请求到数据,会用源站接口再次请求
  3. 接口域名上 CDN
    • 增强可用性、稳定性
  4. 接口降级
    • 这个基于大促备战考虑,核心接口进行降级和用基础接口进行业务实现,比如千人千面的推荐接口,在大促时间点可以直接运营编辑的数据。另外接口万一无法访问,使用预设号的垫底备份数据
  5. 接口监控
    • 监控接口成功率

接口缓存优化

  1. Ajax/fetch 缓存
    • 前端请求时候带上 cache,依赖浏览器本身缓存机制
  2. 本地缓存
    • 异步接口数据优先使用本地 localStorage 中的缓存数据
  3. 多次请求
    • 接口数据本地无 localStorage 缓存数据,重新再次发送 ajax 请求