大家好,林三心又来了。看了十几遍
《康熙王朝》
和《雍正王朝》
,今天,就给大家讲讲“九龙夺嫡”
的那些事,顺便讲讲浏览器渲染
(其实是讲浏览器渲染
,顺便讲讲“九龙夺嫡”
,嘿嘿),觉得讲得好记得给个赞
哦。
毕竟,我也是一个有梦想的作者呢!
主角介绍(模块介绍)
请记住对应的关系哦,有利于后面更好地理解模块之间的关系
康熙(浏览器)
说起咱们的康熙大帝啊,那可就牛逼了,擒鳌拜,平三番,远征葛尔丹。但是也不耽误他风流啊。“九子夺嫡”,说白了就是九个臭小子互相干架争自己老子的皇位,那也怪不得这些臭小子啊,谁叫康熙大帝生那么多呢?当然,九子中最突出的那几个分别是大阿哥胤禔(HTML解析器),老三胤祉(绘图模块),老四胤禛(JS引擎),老八胤禩(CSS解析器),老十三(布局Layout模块)
大阿哥(HTML解析器)
- 性格:康熙的大儿子,身强力壮,喜欢打仗,就是没啥脑子(打仗还被俘虏过,丢人啊)
- 技能:只解析
HTML标签
,顺便解析内联style标签
里的样式,构建DOM树
八阿哥(CSS解析器)
- 性格:康熙的八儿子,表面工作做得很漂亮(每天都在学他老爸,却学的最不像)
- 技能:解析
link
标签里的外联漂亮样式,构建CSS树
四阿哥(JS引擎)
- 性格:康熙的四儿子,最有脑子的儿子,是个腹黑男(后来的雍正帝)
- 技能:暗地里操纵各种
样式
和DOM节点
(增删改查或者绑定事件)
十三阿哥(布局Layout模块)
- 性格:直来直去,豪爽,对各位兄弟都很仗义(这么仗义,不适合做皇帝)
- 技能:把
DOM树
和CSS树
合并,并制成一张布局图纸
(不负责渲染,只提供图纸)
三阿哥(绘图模块)
- 性格:文人一个,好书画,画的一手好画啊(满人是马背上的民族,能将皇位传给你这个文人才怪)
- 技能:接过老十三手中的
图纸
,并绘制
出来给大伙看
大致渲染过程
- 大阿哥(HTML解析器)遇到HTML标签就解析,并构造出DOM树
- 八阿哥(CSS解析器)将link标签里的CSS样式解析,并构建CSS树
- 大阿哥和八阿哥把各自的DOM树和CSS树交给四阿哥(JS引擎)
- 四阿哥(JS引擎)处理script里的js代码,并根据js代码,完成绑定事件,修改CSS树和DOM树等操作
- 十三阿哥(布局Layout模块)将修改后的CSS树和DOM树合成一个渲染树,并设计出布局图纸,交给三阿哥(绘图模块)
- 康熙(浏览器)请求各种图片资源,音频资源等等,一齐交给三阿哥
- 三阿哥(绘图模块)可是画画高手啊,马上根据这张图纸并且皇阿玛给的素材,画出整个页面给大伙看
各位阿哥们之间的关系(模块之间的关系)
看以下内容之前,大家要先明白一个道理:
解析
和渲染
是两个过程,解析
了不一定会渲染
(也就是你还看不到页面效果),渲染
了说明解析
完了,这就好比:你有了钱(解析
)不一定会去买别墅(渲染
),但是如果你买了别墅(渲染
)那说明你是真的有钱(解析
)
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解析器解析的太慢,那么页面就一直无法完成最终渲染,也就会出现一小段时间
白屏现象
- 如何解决问题: 核心就是加快外联样式的加载速度:
- 使用CDN节点进行外部资源加速
- 对外部样式文件进行压缩(使用打包工具,例如webpack,gulp等)
- 优化你的样式文件的代码
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执行速度:
<script async></script>
加上async
属性,JS代码会异步加载并执行<script defer></script>
加上defer
属性,JS代码会异步加载,但是会在DOMCotentLoaded
前执行- 把script标签放在页面尾部
- 优化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
再来看看渲染大致过程:
- 大阿哥(HTML解析器)遇到HTML标签就解析,并构造出DOM树
- 八阿哥(CSS解析器)将link标签里的CSS样式解析,并构建CSS树
- 大阿哥和八阿哥把各自的DOM树和CSS树交给四阿哥(JS引擎)//
DOMContentLoaded
发生在这 - 四阿哥(JS引擎)处理script里的js代码,并根据js代码,完成绑定事件,修改CSS树和DOM树等操作
- 十三阿哥(布局Layout模块)将修改后的CSS树和DOM树合成一个渲染树,并设计出布局图纸,交给三阿哥(绘图模块)
- 康熙(浏览器)请求各种图片资源,音频资源等等,一齐交给三阿哥
- 三阿哥(绘图模块)可是画画高手啊,马上根据这张图纸并且皇阿玛给的素材,画出整个页面给大伙看 //
onload
发生在这
结语
JavaScript
是浏览器中运行的大脑,最能得到浏览器(康熙)青睐的肯定是JavaScript(四阿哥),所以最后肯定是四阿哥胤禛
胜出啦,恭喜雍正帝
!
雍正也是我很喜欢的一位,
推行新政
,火耗归公
,摊丁入亩
,士绅一体当差一体纳粮
,派年羹尧平定罗布赞旦增阿拉布坦叛乱
等等,都很出色!
感兴趣的可以去看看
《雍正王朝》
,和《大明王朝》
并列为中国古装剧的巅峰之作!