191  
查询码:00000782
前端性能优化最佳实践(四)
作者: 朱凡 于 2020年06月26日 发布在分类 / FM组 / FM_App 下,并于 2020年06月26日 编辑

渲染

浏览器渲染原理

经典文章how browser works

那么这个问题考察的就是渲染原理方面的知识点,上面就是市面上主要浏览器对应的渲染引擎,通过这个问题我们就引出了我们今天要介绍的内容。可以看到目前Blink渲染引擎占据了半壁江山,当然Blink的前身都是由Webkit优化改造而来的。也正是因为有这些不同的渲染引擎,大家才会遇到浏览器的兼容性问题,相信随着规范的不断推进,需要我们解决的兼容性问题将会越来越少。渲染原理解析关于渲染原理,我们首先来看这张图,如下:


上图就是整个渲染流程的总体流程图,下面我们来一一介绍渲染流程当中的每个步骤。首先是解析HTML,这个过程主要是把HTML文档解析为DOM树的过程。如果遇到标签会停止解析,先执行标签当中JavaScript;如果是外联方式,也需要等待下载并且执行完对应的JavaScript代码,然后才能够继续执行解析HTML的工作。HTML解析完成后触发DOMContentLoaded事件,这里我们就可以操作DOM了。

生成对应的DOM树结构如下:

Tips:上图中的DOM树节点类型如何获取呢,这里我们可以在Chrome当中选中对应元素,然后在控制台中输入$0.constructor,即可打印出对应的类型,如下:

然后是解析CSS。可以看到解析HTML和解析CSS是并行处理的,也就是这两部分是同时进行的,不然会造成渲染的内容没有对应的样式。解析CSS遇到标签和上面解析HTML的处理方法是一样的,这里不在赘述。CSS解析器将CSS解析成CSSStyleSheet(也被叫做CSSOM树),这里的CSSOM树与DOM树结构类似。解析对应关系如下:



接着由DOM树和CSSOM树一起附着合成渲染树(RenderTree),显而易⻅地我们可以得到这个公式:DOMTree+CSSOMTree=RenderTree。同样这里Render树我们也可以简单用图来表示一下,如下:

图中左侧为DOM树,右侧是Render树,可以看到Render树结构与DOM树是非常相似的,但不是一一对应的。每一个节点是一个RenderObject,包含了我们在样式表中设置的样式,样式的宽高和具体位置是通过Layout(重排)计算得出。

Tips:


元素如果被设置为display:none,在DOM树中依然会显示,但是在Render树中不会显示;元素如果被设置为visibility:none,那么DOM树和Render树中都会显示;我们经常说的脱离文档流,其实就是脱离Render Tree。


白屏应对

⻣架,自动化方案,page-skeleton-webpack-plugin,以及antd的skeleton组件


dom性能优化

少操作dom,用fragment,虚拟dom

回流重绘

event-loop

一个完整的Event Loop过程,可以概括为以下阶段:




Macrotask/Microtask上面我们提到了任务队列,那么任务队列有两种,一种是Macrotask,另外一种是Microtask。从最开始我给出的Event Loop总的流程图,大家可以看出Microtask优先级是高于Macrotask的。Microtask当中的任务也是在执行栈当中的任务执行完成后再进行执行,执行的时候和Macrotask有一些区别,Microtask当中任务不会一个一个压入执行栈,而是所有任务直接压入栈中,当Microtask当中的任务执行完毕后,然后我们再从Macrotask中取栈顶的第一个任务进行执行。


那么哪些任务属于Microtask,哪些任务属于Macrotask呢,这里我做了一个大概的总结,如下:Macrotask:setTimeout、setInterval、I/O、UIRendering、script当中的所有代码、setImmediate(Node)Microtask:process.nextTick(node)、Promise、MutationObserver

Tips:有一些考察较详细的题目,还会考察Microtask当中各种任务的优先级,具体的优先级如下:

process.nextTick> Promise >MutationOberser



实践

防抖节流

节流隔一段时间只触发一次第一个人说了算在时间结束出发


//func是用户传入需要防抖的函数

//wait是等待时间


防抖

完成后再统一发送请求,最后一个人说了算只认最后一次


懒加载

图片懒加载


//获取所有的图片标签

constimgs=document.getElementsByTagName('img')

//获取可视区域的高度

constviewHeight=window.innerHeight||document.documentElement.clientHeight

//num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出

letnum=0

functionlazyload(){

for(leti=num;i(imgs.length;i++) {

//用可视区域高度减去元素顶部距离可视区域顶部的高度

letdistance=viewHeight-imgs[i].getBoundingClientRect().top

//如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出

if(distance>=0){

//给元素写入真实的src,展示图片

imgs[i].src=imgs[i].getAttribute('data-src')

//前i张图片已经加载完毕,下次从第i+1张开始检查是否露出

num=i+1

}

}

}

//监听Scroll事件

window.addEventListener('scroll',lazyload,false);

服务端渲染&&同构移动端优化技巧

svg,虚拟列表,300ms延迟(禁用缩放解决)https://bvau g hn. g ithub.io/react-virtualized/#/components/List


ReactpurecomponentVue

async-component


webpack

可视化优化



tree-shaking删除冗余代码



 推荐知识

 历史版本

修改日期 修改人 备注
2020-06-26 15:52:09[当前版本] 朱凡 创建版本

 附件

附件类型

JPEGJPEG

  目录
    知识分享平台 -V 4.8.7 -wcp