「百毒不侵(二)」戏说 “浏览器渲染”

image.png

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

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

image.png

主角介绍(模块介绍)

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

康熙(浏览器)

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

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. 三阿哥(绘图模块)但是画画高手啊,立刻根据这张图纸而且皇阿玛给的素材,画出整个页面给大伙看

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

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

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代码会异步加载并执行(多script标签状况下,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行)
  2. <script defer></script> 加上defer属性,JS代码会异步加载(若是有多个设置了defer的script标签存在,则会按照顺序执行全部的script,会在DOMCotentLoaded前执行)
  3. 把script标签放在页面尾部
  4. 优化JS代码,加快执行速度

CSS解析器和JS引擎

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

JS引擎和JS引擎

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

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

<script src="index1.js"></script>
<script src="index2.js"></script>
<div></div>
复制代码

会先执行完上边script再执行下边script,由于上方script可能修改dom,下方也修改dom,那确定是排队一个一个来,否则就乱套了浏览器

<script src="index1.js" defer></script>
<script src="index2.js" defer></script>
复制代码

会异步加载,也就是下方可能比上方加载更快,可是最终代码执行仍是会按顺序由上往下,而且在DOMContentLoaded以前执行markdown

<script src="index1.js" async></script>
<script src="index2.js" async></script>
复制代码

会异步加载并异步执行,也就是谁先加载完谁就先执行,不按顺序app

一点点疑问

问:为何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(四阿哥),因此最后确定是四阿哥胤禛胜出啦,恭喜雍正帝

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

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

相关文章
相关标签/搜索