Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端性能优化总结 #11

Open
zoro-web opened this issue Jul 29, 2020 · 0 comments
Open

前端性能优化总结 #11

zoro-web opened this issue Jul 29, 2020 · 0 comments

Comments

@zoro-web
Copy link
Owner

zoro-web commented Jul 29, 2020

本质上,要从用户体验指标考虑页面性能

  1. 页面加载时长
  2. 用户交互反馈时长
  3. Web动画中的帧数
  4. 内存

分析要点

  1. 在无痕窗口分析,以避免历史数据和拓展程序对分析结果造成影响
  2. 利用Network分析网络问题
  3. 利用Performance查看运行过程中的性能数据,深入分析 Web 应用的性能问题,可以查看 Performace 了解使用
  4. Lighthouse 这个工具会给出性能得分和优化建议,帮助分析加载时的性能问题

首屏的显示涉及了哪些技术因素

  1. DNS、HTTP、DOM 解析、CSS 阻塞、JavaScript 阻塞等等
  2. 关键资源个数: 可能阻止网页首次渲染的资源(CSS、JavaScript)
  3. 关键资源大小: 现网页首次渲染所需的总字节数,它是所有关键资源传送文件大小的总和
  4. 关键路径长度: 获取所有关键资源所需的往返次数或总时间

首屏分析

  1. 抓图信息区域 (Network --> 勾选Capture screenshots),可以用来分析用户等待页面加载时间内所看到的内容,分析用户实际的体验情况。比如,如果页面加载 1 秒多之后屏幕截图还是白屏状态,这时候就需要分析是网络还是代码的问题了

Alt text

  1. 分析单个资源的时间线

图片替换文本


3. 分析渲染流水线——这个阶段包括了解析 HTML、下载 CSS、下载 JavaScript、生成 CSSOM、执行 JavaScript、生成布局树、绘制页面一系列操作。 此阶段涉及的知识点: * CSS加载不会阻塞DOM树的构建,但会影响布局树(也叫Render树)的构建 * JavaScript的执行依赖于前面的CSS

通常情况下的瓶颈主要体现在下载 CSS 文件、下载 JavaScript 文件和执行 JavaScript
图片替换文本

优化方案

1.网络传输

  • 减少Timing——Queuing等待时间
    1. Queuing等待时间可能是每个域名最多维护 6 个连接导致,将域名分片,增加单位时间内的可连接数,比如将静态资源放在静态域static
    2. 升级至HTTP2.0
  • 降低TTFB (第一字节时间)
    1. 服务器生成页面数据的时间过久——通过增加各种缓存的技术
    2. 网络的原因,带宽过低——使用CDN来缓存一些静态文件
    3. 发送请求头时带上了多余的用户信息,服务器根据请求信息做了多余的无用功——减少多余信息的传输
  • Content Download 时间过久
    1. 减少文件大小——压缩、去掉无用注释等
  • 减少请求数
    1. CSS/JS合并打包(注意:可能引起单次请求下载时间过长,基于现今HTTP2.0无连接限制,分开下载可能效率更高,需要综合考虑,而且内联无法缓存)
    2. CSS雪碧图(如果升级HTTP2.0就没必要用雪碧图了)、base64

2. 加载时优化

  • 首屏内联 JavaScript、内联 CSS 来移除这两种类型的文件下载,这样获取到 HTML 文件之后就可以直接开始渲染流程了
  • CSS放头部,JS放尾部,可以使DOM尽快构建,使DOMContentLoaded尽快触发
  • 静态资源大小(按需加载、压缩)—— HTML、CSS、JavaScript、image、font等
  • 一些不需要在解析 HTML 阶段使用的 JavaScript 标记上 sync 或者 defer
  • 对于大的 CSS 文件,可以通过媒体查询属性
  • 服务端渲染
  • 预渲染
  • preload与prefetch的使用

3.运行时性能

  • 避免批量DOM操作
    1. 使用createDocumentFragment,或者使用框架Vue、React
  • 减少重排重绘
    1. 使用 class 操作样式,而不是频繁操作 style
    2. position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响
    3. 合理使用will-change(会比较耗内存),可以使用合成线程来处理 CSS 特效或者动画,而不涉及到主线程
    4. DOM属性的读写分离,下面的代码只触发一次重排
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
console.log(div.offsetLeft);
console.log(div.offsetTop);
console.log(div.offsetWidth);
console.log(div.offsetHeight);

得益于浏览器的渲染队列机制,当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。但对于低端浏览器,依然会触发多次重排
  • GPU加速
    1. Canvas2D,布局合成,CSS3转换(transitions),CSS3 3D变换(transforms),WebGL和视频(video)
    2. 这段代码可以强制开启 GPU 加速 transform: translate3d(10px, 10px, 0);
  • 减少 JavaScript 脚本霸占主线程时间
    1. 使用web worker处理计算量大的操作
    2. 避免强制同步布局和布局抖动,避免多次重复渲染
    3. 通过Performance分析长任务,尽可能优化长任务
  • 注意内存泄漏——可使用Memory分析
    1. 避免闭包的过量使用
  • 按需加载
  • 懒加载
  • 防抖节流
    1. window.resize
  • 服务器渲染
  • 正则表达式
典型场景: 文档中的函数或者文本进行匹配的时候。
不好的正则表达式极易引起性能问题。其核心问题在于:js 的正则匹配是基于 NFA 的,易引起回溯问题。
正则引擎分为 NFA(非确定性有限状态自动机),和 DFA(确定性有限状态自动机)。
DFA 对于给定的任意一个状态和输入字符,DFA 只会转移到一个确定的状态。并且 DFA 不允许出现没有输入字符的状态转移。而 NFA 对于任意一个状态和输入字符,NFA 所能转移的状态是一个非空集合。模糊匹配、贪婪匹配、惰性匹配都会带来回溯问题。典型的正则匹配如 (.\*)+\d ,便会进行回溯。那么平时开发的时候
    1. 正则要越精确越好
    2. 改用 DFA 的正则引擎
具体可以参考:浅谈正则表达式原理

4.缓存

  • 浏览器DNS缓存
  • Server Worker——在用户设备缓存Common资源,减少网络请求
  • 强制缓存——Expires、Cache-Control
  • 协商缓存——Last-Modified / If-Modified-Since 、Etag / If-None-Match

5.内存

  • 减少DOM数量,使用虚拟列表等方式
  • 减少事件注册,多使用事件代理
  • 尽可能使用原地算法、减少空间复杂度
  • 注意内存泄漏
    1. 闭包
    2. 全局变量
    3. 删除DOM后事件没有移除
    4. 对象互相引用
    5. 死循环
    6. setTimeout,setInterval执行完了没有clear
    7. Dom中的属性指向一个对象,如果DOM不删除,该对象无法被回收

用户性能监控

  1. 基于 Performance API 采集真实用户数据

参考

浏览器工作原理与实践——https://time.geekbang.org/column/intro/216
关键渲染路径——https://developers.google.com/web/fundamentals/performance/critical-rendering-path
RAIL性能模型——https://web.dev/rail/

最后

@zoro-web zoro-web mentioned this issue Jul 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant