## 优化内容效率 ### 避免不必要的下载 - 消除不必要的资源 - 评估一项资源给用户提供的价值是否可以抵消其开销:比如轮播图,是否有必要把所有的图片都下载下来 ### 优化、压缩必要的资源 - 使用通用压缩程序压缩数据 - 数据预处理:去除注释、合并css等其他内容的特定优化(因此,需要建立一个不同类型内容的清单,然后针对不同类型进行优化) - 基于文本的资源使用 gzip 压缩,现代浏览器均支持并默认使用 gzip。 ### 图像优化: - 消除和替换图像:消除多余的图像、尽可能利用 CSS3 效果替代图像 - 明确什么时候使用矢量图像(简单几何形状),什么时候使用光栅图像(场景复杂) - 高分辨率屏幕尽量使用矢量图像(CSS 像素可能对应好几个设备像素,对应的设备像素越多,屏幕越高清);如果使用光栅图像,可以使用 picture 标签和 srcset 属性优化 - 矢量图对 svg 文件进行压缩、再使用 gzip 压缩;光栅图像减少每个像素需要的位数来压缩图像 - 根据自己需要合理选择有损压缩(去除某些像素数据)和无损压缩(压缩像素数据) - 选择正确的图片格式: | 格式 | 透明度 | 动画 | 浏览器 | | :--: | :--: | :--: | :--: | | GIF | 支持 | 支持 | 所有 | | PNG | 支持 | 不支持 | 所有 | | JPEG | 不支持 | 不支持 | 所有 | | JPEG XR | 支持 | 支持 | IE | | WebP | 支持 | 支持 | Chrome、Opera、Android | ![](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/images/format-tree.png) - 位图的大小由像素个数以及每个像素所需的字节数决定,所以优化位图可以从这两方面入手 综上,有以下优化图像技巧:1)首选矢量格式;2)缩小和压缩 SVG 资产;3)挑选最佳光栅图片格式;4)通过试验为光栅格式找到最佳质量设置;5)移除多余的图像元数据;6)提供缩放的图像;7)自动化、自动化、自动化 ### 网页字体优化 - 选择合适的网页字体格式(TTF, EOT, WOFF, WOFF2) - 压缩字体文件 - 利用 `@font-face` 定义字体系列 - 优化加载和渲染:浏览器必须构建渲染树(它依赖 DOM 和 CSSOM 树),然后才能知道需要使用哪些字体资源来渲染文本。但可以使用脚本立刻加载字体;还可以缓存字体文件 ### HTTP 缓存 - ETag:客户端自动在“If-None-Match” HTTP 请求标头内提供 ETag 令牌。服务器根据当前资源核对令牌。如果它未发生变化,服务器将返回“304 Not Modified”响应,告知浏览器缓存中的响应未发生变化 - Cache-Control: - `no-cache`:不缓存,但必须先与服务器确认返回的响应是否发生了变化,然后才能使用该响应来满足后续对同一网址的请求;`no-store`:无论资源有没有发生变化,必须重新向服务器请求 - `private`:只为单个用户缓存,因此不允许任何中间缓存对其进行缓存。例如,用户的浏览器可以缓存包含用户私人信息的 HTML 网页,但 CDN 却不能缓存。`public`:表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存 - `max-age`:允许存活最长时间 - 定义不同的文件名来废弃原缓存,比如 style.x234dff.css 改为 style.3dss8fe.css ## 关键渲染路径 优化关键渲染路径是指优先显示与当前用户操作有关的内容。通过优化关键渲染路径,我们可以显著缩短首次渲染页面的时间。 ### 构建对象模型 浏览器渲染页面前需要先构建 DOM 和 CSSOM 树。因此,我们需要确保尽快将 HTML 和 CSS 都提供给浏览器。 **文档对象模型(DOM)** 1. 转换: 浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成各个字符。 2. 令牌化: 浏览器将字符串转换成 W3C HTML5 标准规定的各种令牌,例如,“”、“”,以及其他尖括号内的字符串。每个令牌都具有特殊含义和一组规则。 3. 词法分析: 发出的令牌转换成定义其属性和规则的“对象”。 4. DOM 构建: 最后,由于 HTML 标记定义不同标记之间的关系(一些标记包含在其他标记内),创建的对象链接在一个树数据结构内,此结构也会捕获原始标记中定义的父项-子项关系:HTML 对象是 body 对象的父项,body 是 paragraph 对象的父项,依此类推。 **CSS 对象模型(CSSOM)** CSS 字节转换成字符,接着转换成令牌和节点,最后链接到一个称为“CSS 对象模型”(CSSOM) 的树结构内 注意:CSSOM 和 DOM 是独立的数据结构 ### 渲染树构建、布局及绘制 为构建渲染树,浏览器大体上完成了下列工作: 1. 从 DOM 树的根节点开始遍历每个可见节点。 - 某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。 - 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略 2. 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。 3. 发射可见节点,连同其内容和计算的样式。 有了渲染树,我们就可以进入“布局”阶段。 到目前为止,我们计算了哪些节点应该是可见的以及它们的计算样式,但我们尚未计算它们在设备视口内的确切位置和大小---这就是“布局”阶段,也称为“自动重排”。为弄清每个对象在网页上的确切大小和位置,浏览器从渲染树的根节点开始进行遍历。 布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸:所有相对测量值都转换为屏幕上的绝对像素。 最后,既然我们知道了哪些节点可见、它们的计算样式以及几何信息,我们终于可以将这些信息传递给最后一个阶段:将渲染树中的每个节点转换成屏幕上的实际像素。这一步通常称为“绘制”或“栅格化”。 下面简要概述了浏览器完成的步骤: 1. 处理 HTML 标记并构建 DOM 树。 2. 处理 CSS 标记并构建 CSSOM 树。 3. 将 DOM 与 CSSOM 合并成一个渲染树。 4. 根据渲染树来布局,以计算每个节点的几何信息。 5. 将各个节点绘制到屏幕上。 “优化关键渲染路径”就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间。 ### 阻塞渲染的 CSS 默认情况下,CSS 被视为阻塞渲染的资源,这意味着浏览器将不会渲染任何已处理的内容,直至 CSSOM 构建完毕。 CSS 是阻塞渲染的资源。需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间。 通过 CSS“媒体类型”和“媒体查询”来使得一些 CSS 只在特定情况下使用: ```html ``` 请注意“阻塞渲染”仅是指浏览器是否需要暂停网页的首次渲染,直至该资源准备就绪。无论哪一种情况,浏览器仍会下载 CSS 资产,只不过不阻塞渲染的资源优先级较低罢了。 ### 使用 JavaScript 添加交互 脚本在文档的何处插入,就在何处执行。当 HTML 解析器遇到一个 script 标记时,它会暂停构建 DOM,将控制权移交给 JavaScript 引擎;等 JavaScript 引擎运行完毕,浏览器会从中断的地方恢复 DOM 构建。如果是外部 JavaScript 文件,浏览器必须停下来,等待从磁盘、缓存或远程服务器获取脚本,这就可能给关键渲染路径增加数十至数千毫秒的延迟。 ### 评估关键渲染路径 - [Lighthouse](https://developers.google.com/web/tools/lighthouse/) 是一个网络应用审核工具,可以对特定页面运行一系列测试,然后在汇总报告中显示页面的结果。 - 使用 Navigation Timing API 设置您的代码:window.performance.timing ### 分析关键渲染路径性能 ### 优化关键渲染路径 为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素: - 关键资源的数量。 - 关键路径长度。 - 关键字节的数量。 优化关键渲染路径的常规步骤如下: 1. 对关键路径进行分析和特性描述:资源数、字节数、长度。 2. 最大限度减少关键资源的数量:删除它们,延迟它们的下载,将它们标记为异步等。 3. 优化关键字节数以缩短下载时间(往返次数)。 4. 优化其余关键资源的加载顺序:您需要尽早下载所有关键资产,以缩短关键路径长度。 ### PageSpeed 规则和建议 - 消除阻塞渲染的 JavaScript 和 CSS - 优化 JavaScript 的使用 - 首选使用异步 JavaScript 资源 - 避免同步服务器调用 - 延迟解析 JavaScript - 避免运行时间长的 JavaScript - 优化 CSS 的使用 - 将 CSS 置于文档 head 标签内 - 避免使用 CSS import - 内联阻塞渲染的 CSS