DOM解析器不是等文档加载实现才解析的,而是边加载边解析。
网络过程依据收到的content-type=text/html判断是html类型,为该申请创立一个渲染过程,渲染过程筹备好后会在网络过程和渲染过程中建设一个共享数据的管道,网络过程按收到的字节流像水一样的倒进这个管道,渲染过程的html解析器会动静接管字节流将其解析为DOM
字节流Bytes——>分词器Tokens——>生成节点Node——>DOM

  1. 通过分词器将字节流转换成Token,分为TagToken(StartTag、EndTag)和文本Token
  2. Token解析为DOM节点,增加到DOM树,Html中有一个Token栈构造,第一步中生成的Token都会进入这个栈中。如果是StartTagHtml解析器会为Token创立一个Dom节点,而后退出到DOM树中。如果是文本Token,会生成一个文本节点退出DOM树中,不必压入栈。如果是EndTagHtml会查看栈顶元素有没有它的StartTag,有就从栈顶弹出,示意该元素解析实现。

如果在2段div中插入script,解析到(script)会暂停DOM解析,JS脚本实现后,Html解析器复原继续执行。渲染过程接管字节流时,也会开启一个预解析线程,遇到JSCSS文件预解析线程会提前下载这些数据。申请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、执行JShtml下载
策略:1.内联JS,css移除下载。2.缩小文件大小、webpack移除正文,压缩、JSdeferasynccss合成
优化:

  1. 加载阶段:网络,JS脚本,图片,音频,视频文件不会阻塞页面首次渲染。JS,html,css文件会阻塞。构建DOM须要HtmlJS,构建渲染树须要CSS
    (1). 要害资源个数:数据越多,首次加载工夫越长。1.改成内联。2.JS没有DOMCSS操作,加deferasynccssmadio
    (2). 资源大小:资源越小,下载工夫越短。压缩css,js资源。移除正文。
    (3). RTT数量:传输分包,小于14k只用1个RTTRTT次数越多,申请工夫越长,缩小个数或大小。CDN缩小时长。
  2. 交互阶段: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提供了对部分视图封装能力,能够让DOMCSSOMJS运行在部分环境,不会影响到全局。
微服务框架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的作用将模板中内容与全局DOMcss进行隔离,实现元素和款式私有化。能够把影子DOM看成一个作用域,外部款式和元素不会影响全局。全局下要拜访影子内款式元素,通过约定好的接口,互不影响。
只通过影子DOM隔离cssDOM,但不会隔离JSJS能够被拜访,渲染引擎判断temp-componentshadow-root,如是影子DOM会跳过,款式也只会从外部找。