戏说 “浏览器渲染”——女朋友看了都说好

image.png

大家好,林三心又来了。看了十几遍《康熙王朝》《雍正王朝》,今天,就给大家讲讲“九龙夺嫡”的那些事,顺便讲讲浏览器渲染(其实是讲浏览器渲染,顺便讲讲“九龙夺嫡”,嘿嘿),觉得讲得好记得给个哦。

毕竟,我也是一个有梦想的作者呢!

image.png

主角介绍(模块介绍)

请记住对应的关系哦,有利于后面更好地理解模块之间的关系

康熙(浏览器)

说起咱们的康熙大帝啊,那可就牛逼了,擒鳌拜,平三番,远征葛尔丹。但是也不耽误他风流啊。“九子夺嫡”,说白了就是九个臭小子互相干架争自己老子的皇位,那也怪不得这些臭小子啊,谁叫康熙大帝生那么多呢?当然,九子中最突出的那几个分别是大阿哥胤禔(HTML解析器),老三胤祉(绘图模块),老四胤禛(JS引擎),老八胤禩(CSS解析器),老十三(布局Layout模块)

image.png

大阿哥(HTML解析器)

  • 性格:康熙的大儿子,身强力壮,喜欢打仗,就是没啥脑子(打仗还被俘虏过,丢人啊)
  • 技能:只解析HTML标签,顺便解析内联style标签里的样式,构建DOM树

八阿哥(CSS解析器)

  • 性格:康熙的八儿子,表面工作做得很漂亮(每天都在学他老爸,却学的最不像)
  • 技能:解析link标签里的外联漂亮样式,构建CSS树

四阿哥(JS引擎)

  • 性格:康熙的四儿子,最有脑子的儿子,是个腹黑男(后来的雍正帝)
  • 技能:暗地里操纵各种样式DOM节点(增删改查或者绑定事件)

十三阿哥(布局Layout模块)

  • 性格:直来直去,豪爽,对各位兄弟都很仗义(这么仗义,不适合做皇帝)
  • 技能:把DOM树CSS树合并,并制成一张布局图纸(不负责渲染,只提供图纸)

三阿哥(绘图模块)

  • 性格:文人一个,好书画,画的一手好画啊(满人是马背上的民族,能将皇位传给你这个文人才怪)
  • 技能:接过老十三手中的图纸,并绘制出来给大伙看

大致渲染过程

image.png

  1. 大阿哥(HTML解析器)遇到HTML标签就解析,并构造出DOM树
  2. 八阿哥(CSS解析器)将link标签里的CSS样式解析,并构建CSS树
  3. 大阿哥和八阿哥把各自的DOM树和CSS树交给四阿哥(JS引擎)
  4. 四阿哥(JS引擎)处理script里的js代码,并根据js代码,完成绑定事件,修改CSS树和DOM树等操作
  5. 十三阿哥(布局Layout模块)将修改后的CSS树和DOM树合成一个渲染树,并设计出布局图纸,交给三阿哥(绘图模块)
  6. 康熙(浏览器)请求各种图片资源,音频资源等等,一齐交给三阿哥
  7. 三阿哥(绘图模块)可是画画高手啊,马上根据这张图纸并且皇阿玛给的素材,画出整个页面给大伙看

各位阿哥们之间的关系(模块之间的关系)

看以下内容之前,大家要先明白一个道理:解析渲染是两个过程,解析了不一定会渲染(也就是你还看不到页面效果),渲染了说明解析完了,这就好比:你有了钱(解析)不一定会去买别墅(渲染),但是如果你买了别墅(渲染)那说明你是真的有钱(解析

HTML解析器

 <style>
     // 6万行css样式
     .box { background: red } // 最后一行
 </style>
 <div class="box"></div>
 <div></div>
 <div></div>
 <div></div>
复制代码
  • 问: HTML解析器负责解析HTML标签,顺便解析内联style标签里的样式,那么问题来了:style标签里有6万多行样式,会因为解析得太慢,而导致后面的div标签都无法解析并且渲染吗?
  • 答: 不会,HTML解析器是异步解析的,并且阻塞渲染。大阿哥(HTML解析器)从上往下走,碰到了style标签,发现里面实在是太多样式了,判断需要解析很久,便派了四个小兵,先去解析下面的四个div标签并先渲染出来,提高效率。
  • 造成的问题: 由于style里太多样式,所以小兵们解析渲染div标签完,大阿哥却还未解析完style里的样式,所以class=”box”的div标签先渲染出来(无样式),等大阿哥解析完style标签,才会把.box的样式赋给这个渲染出来的div标签,这就导致了这个div标签在页面上出现了无样式 -> 有样式的效果,也就是所谓的闪屏现象
  • 如何解决问题: 少用style内联标签,大阿哥要带兵解析HTML已经够累了,你还让他去解析style标签,不造成’闪屏现象’才怪

HTML解析器和CSS解析器

 // index.css里
  // 6万行css样式
  .box { background: red } // 最后一行


 // html代码
 <link href="index.css"></link> // 引入
 <div class="box"></div>
 <div></div>
 <div></div>
 <div></div>
复制代码
  • 问: CSS解析器负责解析link标签里的外联样式,那么问题来了:link标签外联样式有6万多行,会因为解析得太慢,而导致后面的div标签都无法解析并且渲染吗?
  • 答: 不会阻塞后面div标签的解析,但是阻塞后边div标签的渲染,也就是说,CSS解析器在解析link标签里这6万行样式的同时,HTML解析器已经带了几个小兵去把下面的div标签全解析了,但只是解析了,并未渲染出来,等到CSS解析器把6万行样式解析完,再一次性合并CSS树DOM树并渲染到页面上去
  • 为什么: 因为这么做可以避免闪屏现象提高渲染性能。上面说了闪屏现象就是页面上出现了无样式 -> 有样式的效果,体验很差,所以如何避免呢?最好的办法就是等到最终的DOM树最终的CSS树结合完,再一次性渲染上去,这样页面就不会出现无样式 -> 有样式这样的问题了。多次的渲染现在变成了一次性渲染,那自然是提高了渲染的性能。
  • 造成的问题: 如果CSS解析器解析的太慢,那么页面就一直无法完成最终渲染,也就会出现一小段时间白屏现象
  • 如何解决问题: 核心就是加快外联样式的加载速度:
  1. 使用CDN节点进行外部资源加速
  2. 对外部样式文件进行压缩(使用打包工具,例如webpack,gulp等)
  3. 优化你的样式文件的代码

HTML解析器和JS引擎

// index.js文件
  // 6万多行代码,对dom进行了一系列操作

// html页面
 <script src="index.js"></script> // 引入
 <div id="box"></div>
 <div></div>
 <div></div>
 <div></div>
复制代码
  • 问: JS引擎暗地里操纵各种样式DOM节点(增删改查或者绑定事件),会因为执行script标签的引用代码太慢,而导致后面的div标签都无法解析并且渲染吗?
  • 答: 阻塞后面div标签的解析和渲染,等到JS引擎把所有JS代码加载执行完成,才会放HTML解析器往下解析DOM,并且一次性渲染出来
  • 为什么: 举个反例,在四阿哥(JS引擎)缓慢地执行这6万行代码同时,康熙命令大阿哥(HTML解析器)不要管四阿哥,大胆地往下解析HTML,大阿哥马上带着自己的小兵们马上解析完所有div标签,然后满怀成就感地想跑去康熙面前请功领赏,而此时四阿哥还未执行完他的JS代码,大阿哥跑啊跑啊,跑到康熙面前的一瞬间,四阿哥刚好执行完JS代码,并把大阿哥刚刚解析完的所有标签都删了(毕竟四阿哥拥有操控DOM的能力啊),康熙一看,雷霆大怒:“WDNMD!!!老大,你不是说都解析好了吗?在哪呢??敢骗老子?”对着大阿哥一顿臭骂。大阿哥心想:“老四,WDNMD,敢把老子解析的成功给删了!”后来康熙得知后,便制定了一套规则:以后四阿哥先执行代码,然后再派大阿哥去解析HTML,这样大阿哥就不会做无用功啦!
  • 问题: 如果JS代码执行报错或者执行过慢,那么后面的HTML就会永远无法解析了,那么页面有可能就一直是一片空白。
  • 如何解决问题: 核心就是改变JS代码的执行顺序,或者优化JS执行速度:
  1. <script async></script> 加上async属性,JS代码会异步加载并执行
  2. <script defer></script> 加上defer属性,JS代码会异步加载,但是会在DOMCotentLoaded前执行
  3. 把script标签放在页面尾部
  4. 优化JS代码,加快执行速度

CSS解析器和JS引擎

跟上面HTML解析器和JS引擎同理,只不过是DOM树CSS树的区别

JS引擎和JS引擎

<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
复制代码

会先执行完上边script再执行下边script,因为有可能下边的script依赖于上边的script代码(上方例子,bootstrap依赖于jquery)

一点点疑问

问:为什么CSS解析器只能阻塞HTML渲染但不能阻塞HTML解析,但JS引擎却能同时阻塞HTML的解析和渲染呢?

答:因为CSS并不能操作DOM啊,所以也没必要阻塞HTML解析。但是JS引擎就不一样了,能随意操作DOM,所以需要阻塞HTML解析,避免HTML解析器做无用功。

DOMContentLoaded和onload

再来看看渲染大致过程:

  1. 大阿哥(HTML解析器)遇到HTML标签就解析,并构造出DOM树
  2. 八阿哥(CSS解析器)将link标签里的CSS样式解析,并构建CSS树
  3. 大阿哥和八阿哥把各自的DOM树和CSS树交给四阿哥(JS引擎)// DOMContentLoaded发生在这
  4. 四阿哥(JS引擎)处理script里的js代码,并根据js代码,完成绑定事件,修改CSS树和DOM树等操作
  5. 十三阿哥(布局Layout模块)将修改后的CSS树和DOM树合成一个渲染树,并设计出布局图纸,交给三阿哥(绘图模块)
  6. 康熙(浏览器)请求各种图片资源,音频资源等等,一齐交给三阿哥
  7. 三阿哥(绘图模块)可是画画高手啊,马上根据这张图纸并且皇阿玛给的素材,画出整个页面给大伙看 // onload发生在这

结语

JavaScript是浏览器中运行的大脑,最能得到浏览器(康熙)青睐的肯定是JavaScript(四阿哥),所以最后肯定是四阿哥胤禛胜出啦,恭喜雍正帝

雍正也是我很喜欢的一位,推行新政火耗归公摊丁入亩士绅一体当差一体纳粮派年羹尧平定罗布赞旦增阿拉布坦叛乱等等,都很出色!

感兴趣的可以去看看《雍正王朝》,和《大明王朝》并列为中国古装剧的巅峰之作!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享