DOM
解析器不是等文档加载实现才解析的,而是边加载边解析。
网络过程依据收到的content-type=text/html
判断是html
类型,为该申请创立一个渲染过程,渲染过程筹备好后会在网络过程和渲染过程中建设一个共享数据的管道,网络过程按收到的字节流像水一样的倒进这个管道,渲染过程的html
解析器会动静接管字节流将其解析为DOM
。
字节流Bytes
——>分词器Tokens
——>生成节点Node
——>DOM
- 通过分词器将字节流转换成
Token
,分为TagToken(StartTag、EndTag)
和文本Token
- 将
Token
解析为DOM
节点,增加到DOM
树,Html
中有一个Token
栈构造,第一步中生成的Token
都会进入这个栈中。如果是StartTag
,Html
解析器会为Token
创立一个Dom
节点,而后退出到DOM
树中。如果是文本Token
,会生成一个文本节点退出DOM
树中,不必压入栈。如果是EndTag
,Html
会查看栈顶元素有没有它的StartTag
,有就从栈顶弹出,示意该元素解析实现。
如果在2段div
中插入script
,解析到(script
)会暂停DOM
解析,JS
脚本实现后,Html
解析器复原继续执行。渲染过程接管字节流时,也会开启一个预解析线程,遇到JS
或CSS
文件预解析线程会提前下载这些数据。申请Html
到构建DOM
之间有一段闲暇工夫,构建DOM
树之后css
未下载完之前也会有一段闲暇工夫,可能会有白屏。
<html> <head><link href="them.css" rel="stylesheet" /></head> <body> <div>segmentfault.com</div> <script src="foo.js"></script> <div>思否</div> </body></html>
解析Html
、下载CSS
、下载JS
、生成CSSOM
、执行JS
、生成布局树、绘制页面。
次要空白:下载CSS
、下载JS
、执行JS
、html
下载
策略:1.内联JS
,css
移除下载。2.缩小文件大小、webpack
移除正文,压缩、JS
标defer
或async
,css
合成
优化:
- 加载阶段:网络,
JS
脚本,图片,音频,视频文件不会阻塞页面首次渲染。JS
,html
,css
文件会阻塞。构建DOM
须要Html
和JS
,构建渲染树须要CSS
。
(1). 要害资源个数:数据越多,首次加载工夫越长。1.改成内联。2.JS
没有DOM
或CSS
操作,加defer
或async
。css
加madio
。
(2). 资源大小:资源越小,下载工夫越短。压缩css
,js
资源。移除正文。
(3).RTT
数量:传输分包,小于14k
只用1个RTT
。RTT
次数越多,申请工夫越长,缩小个数或大小。CDN
缩小时长。 - 交互阶段:
JS
脚本,渲染过程渲染帧的速度。
(1). 缩小JS
脚本执行工夫:1.执行函数合成多个工作。2.web workers
。不要霸占主线程太久。
(2). 防止强制同步布局:通过DOM
接口,增加删除元素,须要从新计算款式和布局。批改DOM
前查问相干值。同步布局:JS
强制将计算款式和布局操作提前到当前任务中。如加个元素,而后获取此元素高度,获取就要布局后能力获取。
(3). 防止布局抖动:一次JS
执行中,屡次强布局和抖动。如for
循环中,一直读取属性值,每次读都要进行计算款式和布局。不要在批改DOM
时再去查相干值。
(4). 正当利用css
合成动画,css
合成动画在合成线程上执行。不受主线程限度,尽量用css
合成动画。
(5). 防止频繁垃圾回收,垃圾回收时会占用主线程。优化存储构造,防止小颗粒对象的产生。
DOM
的缺点:DOM
提供了一组JS
接口来遍历或批改节点。JS
操作DOM
会影响到整个渲染流水线。如document.body.appendChild(node)
,往body
节点增加一个元素,首先渲染引擎将node
增加到body
之上,而后触发款式计算、布局、绘制、栅格化。布局和布局抖动问题,会大大降低渲染效率。
虚构DOM
通过JS
和根底数据创立虚构DOM
,由虚构DOM
创立出实在DOM
树,再触发渲染流水线输入屏幕。如果产生扭转就依据新数据创立新的虚构DOM
,而后比拟2颗虚构DOM
找出变动,再把所有变动一次性从新更新实在DOM
树上,更新渲染流水线,生成新页面。react
之前的递归算法比拟多的话会占主线程比拟久,造成卡页面。Fiber
又叫协程,执行算法的时候让出主线程,解决占用工夫久的问题。双缓存,先将计算结果放在另一个缓存区,全副计算完再把后果利用到DOM
上,缩小不必要更新。
渲染引擎会将所有的css
内容解析为CSSOM
。生成布局树的时候,会在CSSOM
中为布局树元素查找款式,2个雷同标签显示的成果会是一样的,渲染引擎不会为他们独自设置款式。css
会影响到DOM
中其它同样标签的款式。JS
也能在任何中央批改DOM
。是妨碍组件化的2个因素。
webComponent
是一套技术的组合,Custom elements
(自定义元素)、shadow DOM
(影子DOM
)、Html templates
(Html
模板)。webComponent
提供了对部分视图封装能力,能够让DOM
、CSSOM
、JS
运行在部分环境,不会影响到全局。
微服务框架qiankun
就是用的这个。
新建一个组件:1.定义模板。2.定义外部css
款式。3.定义JS
行为
<!DOCTYPE html><html> <body> <template id="template"> <style> p{ background-color: brown; color: cornsilk; } div{ width: 200px; background-color: bisque; } </style> <div> <p>text1</p> <p>text2</p> </div> <script> function foo(){ console.log('inner log') } </script> </template> <script> class ShadowDomTemplate extends HTMLElement{ constructor(){ super(); //获取组件模板 const content=document.querySelector('#template').content; //创立影子DOM节点 const shadowDom=this.attachShadow({mode:'open'}); //将模板增加到影子DOM上 shadowDom.appendChild(content.cloneNode(true)); } } customElements.define('temp-component',ShadowDomTemplate); </script> <temp-component></temp-component> </body></html>
渲染出:
<!DOCTYPE html><html> <head></head> <body> <template id="template"> #document-fragment </template> <script></script> <temp-component> #shadow-root(open) <style>...</style> <div>...</div> </temp-component> </body></html>
影子DOM
元素对网页不可见。
影子DOM
的作用将模板中内容与全局DOM
和css
进行隔离,实现元素和款式私有化。能够把影子DOM
看成一个作用域,外部款式和元素不会影响全局。全局下要拜访影子内款式元素,通过约定好的接口,互不影响。
只通过影子DOM
隔离css
和DOM
,但不会隔离JS
。JS
能够被拜访,渲染引擎判断temp-component
下shadow-root
,如是影子DOM
会跳过,款式也只会从外部找。