前端性能优化(四)| 小册免费学

简介: 前面介绍多个前端性能优化的点,现在我们来说一下性能优化的最后一关——页面渲染浏览器渲染的过程我们之前也稍微提过,这里再说一下解析 HTML 文件,构建 DOM 树,同时浏览器主进程负责下载 CSS 文件

f13e9bd95fe23936db9792df8bb05a4.png

前面介绍多个前端性能优化的点,现在我们来说一下性能优化的最后一关——页面渲染

浏览器渲染的过程我们之前也稍微提过,这里再说一下解析 HTML 文件,构建 DOM 树,同时浏览器主进程负责下载 CSS 文件

CSS 文件下载完成,解析 CSS 文件成树形的数据结构,然后结合 DOM 树合并成 RenderObject 树

布局 RenderObject 树 (Layout/reflow),负责 RenderObject 树中的元素的尺寸,位置等计算

绘制 RenderObject 树 (paint),绘制页面的像素信息

浏览器主进程将默认的图层和复合图层交给 GPU 进程,GPU 进程再将各个图层合成(composite),最后显示出页面


重绘(Repaint)


当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。


回流(Reflow)


当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。 会导致回流的操作:

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见的 DOM 元素
  • 激活 CSS 伪类(例如:hover)
  • 查询某些属性或调用某些方法
  • 一些常用且会导致回流的属性和方法,因为这些API需要实时获取,所以会触发回流 clientWidth、clientHeight、clientTop、clientLeftoffsetWidth、offsetHeight、offsetTop、offsetLeftscrollWidth、scrollHeight、scrollTop、scrollLeftscrollIntoView()、scrollIntoViewIfNeeded()、getComputedStyle()、getBoundingClientRect()、scrollTo()

回流比重绘的代价要更高。有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化:浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。

或者我们可以通过“离线操作”的方式来操作DOM

let container = document.getElementById('container')
container.style.display = 'none'
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
...(省略了许多类似的后续操作)
container.style.display = 'block'
复制代码

再有就是css选择器,css选择器每一次遍历都的过程是非常消耗性能的,应该减小那些没有必要的选择器堆叠,比如#container li{}虽然看起来搜索范围很小,从具体的id选择器中找li元素,但是实际上在选择元素时是从右向左寻找的,会先找所有的li,然后再找#container下面的,不如直接设置类选择器。

JS 引擎是独立于渲染引擎存在的,我们在第一节也说过,当HTML文档中引入script脚本时会阻塞浏览器解析DOM和CSSOM,脚本执行完成之后才会继续解析,对此我们可已使用异步defer或者async脚本

<script async src="index.js"></script>
<script defer src="index.js"></script>
复制代码

async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行,defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始执行。

服务端渲染

服务端渲染是在服务端将首屏的HTML文档渲染好之后在发送给客户端,解决了客户端加载首屏过长的问题,我们现在绝大多数的webApp都是客户端渲染,HTML文档中只有一个根节点,往往是这个样子的

<body>
  <div id="app"></div>
</body>
复制代码

只有一个根节点,根据后期的js运行来渲染页面内容,这就需要等待js全部加载完成才能开始渲染,这就导致了首屏时间过长,所以出现了服务端渲染的技术来解决首屏加载时间长的问题,服务端渲染并不是javaweb那种每切换一次网页都在服务端获取一次HTML,而是通过第一册请求的url将首屏的HTML文档直接填充内容,客户端在获取资源之后直接渲染就是了,之后切换路由也不需要再去请求HTML文件,只需要ajax交互就行了

具体的实现细节可以看我之前的SSR实现

服务端渲染固然能带来用户体验的提升,但是牺牲的同样是服务器的计算资源,服务端渲染本质上是本该浏览器做的事情,分担给服务器去做,当服务器顶不住压力时,这又是一波“反向优化”


相关文章
|
1月前
|
缓存 搜索推荐 前端开发
《VitePress 简易速速上手小册》第6章 性能优化与 SEO(2024 最新版)
《VitePress 简易速速上手小册》第6章 性能优化与 SEO(2024 最新版)
89 1
|
1月前
|
缓存 前端开发 搜索推荐
博客有点丑,魔改优化来一波🛠️
博客有点丑,魔改优化来一波🛠️
76 1
|
7月前
|
安全 调度 C语言
《C++避坑神器·十九》C++多线程使用,啥也不懂看它就对了
《C++避坑神器·十九》C++多线程使用,啥也不懂看它就对了
72 0
|
前端开发 API
canvas深入浅出(二)| 小册免费学
上一节最后我们说了一个绘制曲线的API——arc(那个API并不是专门用来绘制圆形,只是使用曲线可以绘制圆形),他还有一个兄弟——arcTo(x1, y1, x2, y2, r),根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径
68 0
canvas深入浅出(二)| 小册免费学
|
前端开发 API
canvas深入浅出(三)| 小册免费学
所有的内容都是手动绘制还是有点麻烦,好在canvas支持导入图片,createPattern(image, type),该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。
76 0
canvas深入浅出(三)| 小册免费学
彻底搞懂微信小游戏中的分享功能
作为一个游戏,分享功能是必不可少的,尤其是对于一个微信小游戏来说,其最大的优势就是可以借助微信方便的进行分享。 在微信小游戏制作工具中,与分享有关的积木块并不多,一共就 5 块。
255 0
|
缓存 前端开发 网络协议
前端性能优化(二)| 小册免费学
上一节介绍了网页加载过程中可优化的点,这一节我来说一下网络部分的优化。
69 0
|
域名解析 缓存 网络协议
前端性能优化(一)| 小册免费学
移动互联网时代,用户对于网页的打开速度要求越来越高。首屏作为直面用户的第一屏,其重要性不言而喻。优化用户体验更是我们前端开发非常需要 focus 的东西之一。
66 0
|
存储 Web App开发 缓存
前端性能优化(三)| 小册免费学
上一讲我们说到了HTTP缓存,这一讲的缓存并不单单指HTTP缓存
78 0
|
XML 前端开发 JavaScript
canvas深入浅出(一)| 小册免费学
canvas是为了解决页面只能显示静态图片而出现的一种可以使用JavaScript绘制的HTML标签,它可以接受两个参数width和height(原来有三个,还有一个moz-opaque控制透明度,已经废弃了)
66 0