Open jtwang7 opened 2 years ago
参考文章:
- DNS解析阶段 利用 DNS prefetch 技术,对特定域名进行预解析,浏览器会在页面加载完毕后进行该过程。 <link ref="dns-prefetch" href=""> - 客户端发送HTTP请求阶段 1. 减少请求次数: - 资源合并【Webpack打包技术】 - 利用浏览器缓存【协商缓存;强缓存】 2. 缩小请求体积: - 资源(图片/代码/...)压缩【gzip压缩;webpack压缩】 - 图片优化【CSS3代替图片;webp格式;适当降低图片质量】 3. 使用 HTTP2.0: - 二进制传输 - 头部压缩 - 多路复用 - 服务端推送 - 服务端发送HTTP响应阶段 1. 减少响应时间: - 静态资源使用 CDN 2. 降低页面初始渲染时间: - SSR 服务器渲染 - 页面渲染阶段 1. 减少阻塞: - 避免JS、CSS的阻塞 2. 减少渲染次数: - 避免回流与重绘 3. 减少渲染节点的数量: - (图片/DOM) 懒加载 4. 提高渲染效率: - 减少DOM节点的操作【防抖;节流】 - 利用事件循环及异步更新
一个完整的 HTTP 请求需要经历 DNS 查找,TCP 握手,浏览器发出 HTTP 请求,服务器接收请求,服务器处理请求并发回响应,浏览器接收响应等过程。请求中每个环节都会占用一定的时间,而真正下载数据的时间在其中仅占用一小部分。因此建议将多个小文件合并为一个大文件,减少 HTTP 请求次数的原因,避免在建立请求过程中消耗过多的时间。
HTTP2.0 相较于 HTTP1.1 而言,引入了新特性,加快了建立连接和传输数据的效率:
客户端渲染: 获取 HTML 文件,根据需要下载 JavaScript 文件,运行文件,生成 DOM,再渲染。 服务端渲染:服务端返回 HTML 文件,客户端只需解析 HTML。
内容分发网络(CDN)是一组分布在多个不同地理位置的 Web 服务器。当服务器离用户越远时,延迟越高。CDN 就是为了解决这一问题,在多个位置部署服务器,让用户离服务器更近,从而缩短请求时间。
当用户访问一个网站时,如果没有 CDN,过程是这样的:
如果用户访问的网站部署了 CDN,过程是这样的:
JS 放在底部的原因: JS 加载和执行会阻塞 HTML 解析,浏览器碰到 JS 会先下载和处理 JS 文件,停止之前的 HTML 解析直到 JS 执行结束。 若 JS 中还存在 CSS 操作,则会先等待 CSS 文件全部加载完成,再执行 JS 代码,最后恢复 HTML 构建。
JS 文件也不是不可以放在头部,只要给 script 标签加上 defer 属性就可以了,异步下载,延迟执行。
CSS 放在头部的原因: 先加载 HTML 再加载 CSS,会让用户第一时间看到的页面是没有样式的、“丑陋”的。为了避免这种情况发生,就要将 CSS 文件放在头部了。
参考:浏览器缓存 为了避免用户每次访问网站都得请求文件,浏览器提供了强缓存、协商缓存等手段。 强缓存:Expires(绝对时间);Cache-Control: max-age=xxx(相对时间) 协商缓存:Last-Modified(服->客) / If-Modified-Since(客->服);Etag(服->客) / If-None-Match(客->服)
Expires(绝对时间)
Cache-Control: max-age=xxx(相对时间)
Last-Modified(服->客) / If-Modified-Since(客->服)
Etag(服->客) / If-None-Match(客->服)
采用缓存策略,会产生一个问题:当文件更新了怎么办?怎么通知浏览器重新请求文件? 可以通过更新页面中引用的资源链接地址,让浏览器主动放弃缓存,加载新资源。 具体做法: 把资源地址 URL 的修改与文件内容关联起来,也就是说,只有文件内容变化,才会导致相应 URL 的变更,从而实现文件级别的精确缓存控制。什么东西与文件内容相关呢?我们会很自然的联想到利用数据摘要要算法对文件求摘要信息,摘要信息与文件内容一一对应,就有了一种可以精确到单个文件粒度的缓存控制依据了。
压缩文件可以减少文件下载时间,让用户体验性更好。 在 webpack 中可以使用如下插件进行压缩:
使用 gzip 压缩: 可以通过向 HTTP 请求头中的 Accept-Encoding 头添加 gzip 标识来开启这一功能。当然,服务器也得支持这一功能。
懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
参考:my-issue:JS深入浅出 - 浏览器的重绘(Repaint)与回流(Reflow) 浏览器的优化机制: 由于每次回流/重绘都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列。等队列中的操作到了一定的数量或者到了一定的时间间隔(取决于浏览器的重绘频率,一般近似于显示器的刷新频率60Hz),浏览器就会 flush 清空队列,进行一个批处理。上述优化机制能够让多次的回流、重绘变成一次回流重绘。 但是,某些操作会强制浏览器立即清空回调队列中的回流/重绘操作:
clientWidth、clientHeight、clientTop、clientLeft offsetWidth、offsetHeight、offsetTop、offsetLeft scrollWidth、scrollHeight、scrollTop、scrollLeft scrollIntoView()、scrollIntoViewIfNeeded() getComputedStyle() getBoundingClientRect() scrollTo()
浏览器为了给你最精确的值,需要flush队列,因为队列中可能会有影响到这些值的操作。即使你获取元素的布局和样式信息跟最近发生或改变的布局信息无关,浏览器都会强行刷新渲染队列。引擎会重新渲染来确保获取的值是实时的。
CSS
JavaScript
总结:减少对 render tree 的操作(合并多次多DOM和样式的修改),并减少对一些 style 信息的请求,尽量利用好浏览器的优化策略。
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
在 CSS 中,transforms 和 opacity 这两个属性更改不会触发重排与重绘,它们是可以由合成器(composite)单独处理的属性。 因此我们可以利用这两个属性,结合 transition 等动画 API 实现过渡效果等。
前端性能优化
参考文章:
各阶段优化操作
导航
内容
一个完整的 HTTP 请求需要经历 DNS 查找,TCP 握手,浏览器发出 HTTP 请求,服务器接收请求,服务器处理请求并发回响应,浏览器接收响应等过程。请求中每个环节都会占用一定的时间,而真正下载数据的时间在其中仅占用一小部分。因此建议将多个小文件合并为一个大文件,减少 HTTP 请求次数的原因,避免在建立请求过程中消耗过多的时间。
HTTP2.0 相较于 HTTP1.1 而言,引入了新特性,加快了建立连接和传输数据的效率:
客户端渲染: 获取 HTML 文件,根据需要下载 JavaScript 文件,运行文件,生成 DOM,再渲染。 服务端渲染:服务端返回 HTML 文件,客户端只需解析 HTML。
内容分发网络(CDN)是一组分布在多个不同地理位置的 Web 服务器。当服务器离用户越远时,延迟越高。CDN 就是为了解决这一问题,在多个位置部署服务器,让用户离服务器更近,从而缩短请求时间。
CDN 原理
当用户访问一个网站时,如果没有 CDN,过程是这样的:
如果用户访问的网站部署了 CDN,过程是这样的:
JS 放在底部的原因: JS 加载和执行会阻塞 HTML 解析,浏览器碰到 JS 会先下载和处理 JS 文件,停止之前的 HTML 解析直到 JS 执行结束。 若 JS 中还存在 CSS 操作,则会先等待 CSS 文件全部加载完成,再执行 JS 代码,最后恢复 HTML 构建。
CSS 放在头部的原因: 先加载 HTML 再加载 CSS,会让用户第一时间看到的页面是没有样式的、“丑陋”的。为了避免这种情况发生,就要将 CSS 文件放在头部了。
参考:浏览器缓存 为了避免用户每次访问网站都得请求文件,浏览器提供了强缓存、协商缓存等手段。 强缓存:
Expires(绝对时间)
;Cache-Control: max-age=xxx(相对时间)
协商缓存:Last-Modified(服->客) / If-Modified-Since(客->服)
;Etag(服->客) / If-None-Match(客->服)
采用缓存策略,会产生一个问题:当文件更新了怎么办?怎么通知浏览器重新请求文件? 可以通过更新页面中引用的资源链接地址,让浏览器主动放弃缓存,加载新资源。 具体做法: 把资源地址 URL 的修改与文件内容关联起来,也就是说,只有文件内容变化,才会导致相应 URL 的变更,从而实现文件级别的精确缓存控制。什么东西与文件内容相关呢?我们会很自然的联想到利用数据摘要要算法对文件求摘要信息,摘要信息与文件内容一一对应,就有了一种可以精确到单个文件粒度的缓存控制依据了。
压缩文件可以减少文件下载时间,让用户体验性更好。 在 webpack 中可以使用如下插件进行压缩:
使用 gzip 压缩: 可以通过向 HTTP 请求头中的 Accept-Encoding 头添加 gzip 标识来开启这一功能。当然,服务器也得支持这一功能。
懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
参考:my-issue:JS深入浅出 - 浏览器的重绘(Repaint)与回流(Reflow) 浏览器的优化机制: 由于每次回流/重绘都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列。等队列中的操作到了一定的数量或者到了一定的时间间隔(取决于浏览器的重绘频率,一般近似于显示器的刷新频率60Hz),浏览器就会 flush 清空队列,进行一个批处理。上述优化机制能够让多次的回流、重绘变成一次回流重绘。 但是,某些操作会强制浏览器立即清空回调队列中的回流/重绘操作:
浏览器为了给你最精确的值,需要flush队列,因为队列中可能会有影响到这些值的操作。即使你获取元素的布局和样式信息跟最近发生或改变的布局信息无关,浏览器都会强行刷新渲染队列。引擎会重新渲染来确保获取的值是实时的。
减少回流和重绘
CSS
JavaScript
总结:减少对 render tree 的操作(合并多次多DOM和样式的修改),并减少对一些 style 信息的请求,尽量利用好浏览器的优化策略。
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
在 CSS 中,transforms 和 opacity 这两个属性更改不会触发重排与重绘,它们是可以由合成器(composite)单独处理的属性。 因此我们可以利用这两个属性,结合 transition 等动画 API 实现过渡效果等。