浏览器工作原理与实践
李兵
前盛大创新院高级研究员
立即订阅
6167 人已学习
课程目录
已完结 42 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 参透了浏览器的工作原理,你就能解决80%的前端难题
免费
宏观视角下的浏览器 (6讲)
01 | Chrome架构:仅仅打开了1个页面,为什么有4个进程?
02 | TCP协议:如何保证页面文件能被完整送达浏览器?
03 | HTTP请求流程:为什么很多站点第二次打开速度会很快?
04 | 导航流程:从输入URL到页面展示,这中间发生了什么?
05 | 渲染流程(上):HTML、CSS和JavaScript,是如何变成页面的?
06 | 渲染流程(下):HTML、CSS和JavaScript,是如何变成页面的?
浏览器中的JavaScript执行机制 (5讲)
07 | 变量提升:JavaScript代码是按顺序执行的吗?
08 | 调用栈:为什么JavaScript代码会出现栈溢出?
09 | 块级作用域:var缺陷以及为什么要引入let和const?
10 | 作用域链和闭包 :代码中出现相同的变量,JavaScript引擎是如何选择的?
11 | this:从JavaScript执行上下文的视角讲清楚this
V8工作原理 (3讲)
12 | 栈空间和堆空间:数据是如何存储的?
13 | 垃圾回收:垃圾数据是如何自动回收的?
14 | 编译器和解释器:V8是如何执行一段JavaScript代码的?
浏览器中的页面循环系统 (6讲)
15 | 消息队列和事件循环:页面是怎么“活”起来的?
16 | WebAPI:setTimeout是如何实现的?
17 | WebAPI:XMLHttpRequest是怎么实现的?
18 | 宏任务和微任务:不是所有任务都是一个待遇
19 | Promise:使用Promise,告别回调函数
20 | async/await:使用同步的方式去写异步代码
浏览器中的页面 (8讲)
21 | Chrome开发者工具:利用网络面板做性能分析
22 | DOM树:JavaScript是如何影响DOM树构建的?
23 | 渲染流水线:CSS如何影响首次加载时的白屏时间?
24 | 分层和合成机制:为什么CSS动画比JavaScript高效?
25 | 页面性能:如何系统地优化页面?
26 | 虚拟DOM:虚拟DOM和实际的DOM有何不同?
27 | 渐进式网页应用(PWA):它究竟解决了Web应用的哪些问题?
28 | WebComponent:像搭积木一样构建Web应用
浏览器中的网络 (3讲)
29 | HTTP/1:HTTP性能优化
30|HTTP/2:如何提升网络速度?
31|HTTP/3:甩掉TCP、TLS 的包袱,构建高效网络
浏览器安全 (5讲)
32 | 同源策略:为什么XMLHttpRequest不能跨域请求资源?
33 | 跨站脚本攻击(XSS):为什么Cookie中有HttpOnly属性?
34 | CSRF攻击:陌生链接不要随便点
35 | 安全沙箱:页面和系统之间的隔离墙
36 | HTTPS:让数据传输更安全
结束语 (1讲)
结束语 | 大道至简
课外加餐 (4讲)
加餐一|浏览上下文组:如何计算Chrome中渲染进程的个数?
加餐二|任务调度:有了setTimeOut,为什么还要使用rAF?
加餐三|加载阶段性能:使用Audits来优化Web性能
加餐四|页面性能工具:如何使用Performance?
浏览器工作原理与实践
登录|注册

22 | DOM树:JavaScript是如何影响DOM树构建的?

李兵 2019-09-24
上一篇文章中,我们通过开发者工具中的网络面板,介绍了网络请求过程的几种性能指标以及对页面加载的影响。
而在渲染流水线中,后面的步骤都直接或者间接地依赖于 DOM 结构,所以本文我们就继续沿着网络数据流路径来介绍 DOM 树是怎么生成的。然后再基于 DOM 树的解析流程介绍两块内容:第一个是在解析过程中遇到 JavaScript 脚本,DOM 解析器是如何处理的?第二个是 DOM 解析器是如何处理跨站点资源的?

什么是 DOM

从网络传给渲染引擎的 HTML 文件字节流是无法直接被渲染引擎理解的,所以要将其转化为渲染引擎能够理解的内部结构,这个结构就是 DOM。DOM 提供了对 HTML 文档结构化的表述。在渲染引擎中,DOM 有三个层面的作用。
从页面的视角来看,DOM 是生成页面的基础数据结构。
从 JavaScript 脚本视角来看,DOM 提供给 JavaScript 脚本操作的接口,通过这套接口,JavaScript 可以对 DOM 结构进行访问,从而改变文档的结构、样式和内容。
从安全视角来看,DOM 是一道安全防护线,一些不安全的内容在 DOM 解析阶段就被拒之门外了。
简言之,DOM 是表述 HTML 的内部数据结构,它会将 Web 页面和 JavaScript 脚本连接起来,并过滤一些不安全的内容。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《浏览器工作原理与实践》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(23)

  • Luke
    CSS不阻塞dom的生成。
    CSS不阻塞js的加载,但是会阻塞js的执行。
    js会阻塞dom的生成,也就是会阻塞页面的渲染,那么css也有可能会阻塞页面的渲染。
    如果把CSS放在文档的最后面加载执行,CSS不会阻塞DOM的生成,也不会阻塞JS,但是浏览器在解析完DOM后,要花费额外时间来解析CSS,而不是在解析DOM的时候,并行解析CSS。
    并且浏览器会先渲染出一个没有样式的页面,等CSS加载完后会再渲染成一个有样式的页面,页面会出现明显的闪动的现象。
    所以应该把CSS放在文档的头部,尽可能的提前加载CSS;把JS放在文档的尾部,这样JS也不会阻塞页面的渲染。CSS会和JS并行解析,CSS解析也尽可能的不去阻塞JS的执行,从而使页面尽快的渲染完成。
    2019-09-25
    2
    16
  • Angus
    会显示time.geekbang和test,JavaScript代码执行的时候第二个div还没有生成DOM节点,所以是获取不到div2的,页面会报错Uncaught TypeError: Cannot set property 'innerText' of undefined。

    另外复习了下async和defer:

    async:脚本并行加载,加载完成之后立即执行,执行时机不确定,仍有可能阻塞HTML解析,执行时机在load事件派发之前

    defer:脚本并行加载,等待HTML解析完成之后,按照加载顺序执行脚本,执行时机在DOMContentLoaded事件派发之前
    2019-09-24
    1
    7
  • mfist
    开始看文章的时候就在想如果js获取的dom还没有解析出来,会如何处理,结果思考题就是这个。

    会两行显示,一行是time.geekbang 另外一行是test。原因是script脚本执行的时候获取想不到第二个div,所以不会对后来的div有影响。

    今日总结:
    1. 首先介绍了什么是DOM(表述渲染引擎内部数据结构,它将Web页面和JavaScript脚本连接起来,并过滤不安全内容)、DOM树如何生成(网络进程和渲染进程建立一个流式管道,HTML解析器直接解析,不需要等待text/html类型的接口 接受完毕再进行解析),第一步:通过分词器将字节流转换为Token;第二步:将Token解析为DOM节点;第三步:将DOM节点添加到DOM树中。
    2. JavaScript是如何影响DOM生成的?暂停html解析,下载解析执行完毕js之后再进行html解析(如果这期间使用到了cssDom,需要等待相应css过程)。预解析线程的优化(提前加载相应js css文件)
    3. 渲染引擎还有一个安全检查模块XSSAuditor用来检测词法安全的
    2019-09-24
    3
  • 忘忧草的约定
    老师请问一下:主线程在parseHtml时,是不是没办法执行执行paint等操作、那这时候页面又是如何绘制出来的呀?

    作者回复: 如果正在执行ParserHTML,那么页面只会显示之前绘制好的内容,举个极端点的例子,比如ParserHTML占用了主线程10秒,那么这10秒内,页面都不会发生新的绘制操作,也就是页面卡顿了10秒!

    2019-11-16
    1
  • Peter Cheng
    针对文章中js和css加载我有一个疑问。
    <head>
    <link ref="a.css">
    <script src="b.js"></scripit>
    <link ref="c.css">
    </head>
    这三个资源的加载顺序是什么。按照老师文章中的意思,是先加载css文件,再加载js文件吗。
    即a.css,c.css,b.js。
    2019-09-25
    3
    1
  • 王大可
    time.geekbang
    test
    把script标签包裹的代码放入一个js文件中,在引入该文件
    1. 放入第一个div之前页面显示
    1
    test
    控制台报错;
    2. 放入最后一个div之前页面显示
    time.geekbang
    time.geekbang.com ;
    3.放入任何位置加入defer或async 显示
    time.geekbang
    time.geekbang.com
    2019-09-24
    1
  • 极客时间
    1、html页面中如果只引入了css没有引入js,那么css不会组织html解析dom。
    2、html页面中如果同时引入了css和js,那么由于css会阻塞js的执行,那么css会间接阻塞html解析dom。
    不知道这个结论是否正确。
    2019-12-10
  • 番茄
    老师,dom 操作怎么和渲染事件关联起来,比如一段js代码中有 div1.style.color = 'red',我测试了一下,是立刻生效的,但是当前js还没有执行完。dom 操作不应该生成一个宏任务,再执行吗?
    2019-11-05
  • Lx
    即使js脚本设置了a sync defer,也还是会被css的文件下载阻塞吧?
    2019-10-20
  • Lx
    从安全视角来看,DOM 是一道安全防护线,一些不安全的内容在 DOM 解析阶段就被拒之门外了。

    这句话怎么理解呢
    2019-10-20
  • Cris
    额外说明一下,渲染引擎还有一个安全检查模块叫 XSSAuditor,是用来检测词法安全的。老师XssAuditor也是渲染进程里的一个线程吗?
    2019-10-15
  • 欣欣向荣的万七七
    讲得太赞了!一直以来我都只记着加载表现结果(大部分文章都并不知道细节原因,而只能从做测试得到的结果来推测)。而老师的视角则可以从运行时进行讲解 这种知识是很难得的呀~
    2019-10-02
  • 蓝配鸡
    思考题看法:
    会生成
    time.geekbang
    Test

    第二段js没有执行成功是因为在那个时间节点还找不到第二个div
    2019-09-28
  • 木瓜777
    您好,网络进程接收到响应头之后,会根据请求头中的 content-type 字段来判断文件的类型,比如 content-type 的值是“text/html”!
    这个地方应该是根据响应头判断文件类型吧?

    作者回复: 嗯 是响应头,我改过来

    2019-09-27
  • 叫我大胖就好了
    我看MDN写的是defer在DOMContentLoaded 前执行

    作者回复: 你是对的,我写错了。

    2019-09-26
  • Hurry
    Token 栈,遇到结束标签,但是栈顶刚好不是对应开始标签, 这种错误,解析器,如何处理?
    2019-09-26
  • GY
    2点疑惑望解答
    1.既然是先进行html解析,那么当html解析器遇到style标签和行内样式时,会怎么做,是一个怎样的流程,或者说什么时候进行样式计算呢
    2.文中有一段是这样说的:而 JavaScript 引擎在解析 JavaScript 之前,是不知道 JavaScript 是否操纵了 CSSOM 的,所以渲染引擎在遇到 JavaScript 脚本时,不管该脚本是否操纵了 CSSOM,都会执行 CSS 文件下载,解析操作,再执行 JavaScript 脚本。
    按照这个说法,css不是会阻塞html解析吗,而这段话上面又说,遇到操作cssom才会去下载并解析,又跟这段有点歧义
    2019-09-25
  • 歌在云端
    time.geekbang 和 test
    2019-09-25
  • ytd
    第一行是time.geekbang,第二行不会变,仍是test。原因就是浏览器是边加载边解析html的,而且遇到js会停止dom的解析执行js,js执行完毕后再接着解析dom。上面的代码,js执行时第2个div并未被解析为dom,所以js中获取不到,js会抛出错误TypeError,但js抛出错误并未影响html的继续解析。所以,第2个div保持原来的状态被解析出来。
    2019-09-25
  • HB
    每节课都能学到东西,如果能更新快一点就好了。比如二四六改成一三五七
    2019-09-24
    2
收起评论
23
返回
顶部