浏览器工作原理与实践(五)

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未下载完之前也会有一段空闲时间,可能会有白屏。


    
    
        
segmentfault.com
思否

解析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行为



  
    
    
    
  

渲染出:



  
  
    
    
    
      #shadow-root(open)
      
      
...

影子DOM元素对网页不可见。
影子DOM的作用将模板中内容与全局DOMcss进行隔离,实现元素和样式私有化。可以把影子DOM看成一个作用域,内部样式和元素不会影响全局。全局下要访问影子内样式元素,通过约定好的接口,互不影响。
只通过影子DOM隔离cssDOM,但不会隔离JSJS可以被访问,渲染引擎判断temp-componentshadow-root,如是影子DOM会跳过,样式也只会从内部找。

你可能感兴趣的:(javascript)