摘要:浏览器对html文件中css、js、dom的解析

1.确立概念

首先一个资源从网上下载到浏览肯定要下载,下文称之为下载。
从网上下载到本地后读它的内容这个过程,下文称之为解析。

将HTML文件的解析过程,称为dom解析。css解析的过程为cssdom构建。cssdom构建完成后会和dom解析一块构成render(渲染)树,然后render(渲染)树会被painting成我们看到的网页。

页面解析顺序严格按照标签出现的前后顺序(css文件除外),除非<script>标签被指定为defer或async属性。两个css文件谁先接收数据谁先解析,不分先后,但是标签中后出现的css决定前面出现的css。

2.dom解析和css,javascript解析的关系

  • 浏览器首先下载html文件,然后将html文件解析,dom可以边下载边解析。
  • 当遇到一个<link>标签后发起一个对css文件的请求,同时dom可以继续解析。css可以边下载边解析,对css解析时dom解析会被阻塞。关于对css解析时dom解析会被阻塞这一问题有人说不会被阻塞,但是我通过Chrome中的perfromance面板,没有观察到css解析和dom解析一块运行的情况。
  • 当遇到一个<script src>标签后发起一个对js文件的请求,这时dom不能继续解析,css也不能继续解析,js文件不能边下载边运行。只能等到js脚本下载并且运行完成后才能继续解析dom文件和css文件。

3.浏览器对文件的加载顺序会有优化

  • 会把几个文件请求积攒起来,最后统一发送,这个优化规则不是很清楚
  • 推测性解析:“推测性”解析就是,当让渲染引擎干等着js代码加下和运行的时候,会起一个第三个进程,简单的搜索要下载的资源,比如css和js,然后下载。此时dom解析不会被下载的js阻塞,只有当运行到请求js文件的那一行,对应的js才能运行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>keepnight</title>
<link rel="stylesheet" type="text/css" href="5.css" />
</head>
<body>

<h1>我的第一个 JavaScript 程序</h1>
<p>这是一个段落</p> <!--重复1000次-->


<script src="41.js"></script>
<img src="https://www.keepnight.com/img/icon.ico"/>

</body>
</html>

如上面代码所示
从逻辑上应该

Send Request (对html的请求)
Parse html (解析dom)
Send Request (对5.css的请求)
Parse html (解析dom)
Send Request (对41.js的请求)
Send Request (对icon.ico的请求)

但浏览器会进行一定的优化,实际上是下面的

Send Request (对html的请求)
Parse Html (解析dom)
Send Request (对5.css的请求)
Send Request (对41.js的请求)
Send Request (对icon.ico的请求)
Parse Html (解析dom)

4.代码分析

dom的页面解析顺序严格按照标签出现的前后顺序(css文件除外),除非<script>标签被指定为defer或async属性。两个css文件谁先下载完谁先解析,不分先后。

代码一:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>keepnight</title>
<link rel="stylesheet" type="text/css" href="5.css" />
<link rel="stylesheet" type="text/css" href="6.css" />
</head>
<body>

<h1>我的第一个 JavaScript 程序</h1>
<p>这是一个段落</p> 

<script src="41.js"></script>


</body>
</html>

1.第一种情况
同时对5.css,6.css,41.js发送请求,假设5.css先下载完,6.css后下载完,41.js最后下载完

上面的代码解析顺序为


Parse Stylesheet (解析5.css)
Parse Stylesheet (解析6.css)
Evaluate Script (解析41.js)

2.第二种情况
同时对5.css,6.css,41.js发送请求,假设6.css先下载完,5.css后下载完,41.js最后下载完

上面的代码解析顺序为

Parse Stylesheet (解析6.css)
Parse Stylesheet (解析5.css)
Evaluate Script (解析41.js)

3.第三种情况
同时对5.css,6.css,41.js发送请求,假设5.css先下载完,41.js后下载完,6.css最后下载完

上面的代码解析顺序为

Parse Stylesheet (解析5.css)
Parse Stylesheet (解析6.css)
Evaluate Script (解析41.js)

4.第四种情况
同时对5.css,6.css,41.js发送请求,假设41.js先下载完,5.css后下载完,6.css最后下载完41.js会严格按照标签顺序执行

上面的代码解析顺序为

Parse Stylesheet (解析5.css)
Parse Stylesheet (解析6.css)
Evaluate Script (解析41.js)

5.第五种情况
同时对5.css,6.css,41.js发送请求,假设5.css先下载完,6.css后下载完,41.js最后下载完

上面的代码解析顺序为

Parse Stylesheet (解析5.css,此时5.css只下载一半)
Parse Stylesheet (解析6.css)
(此时5.css下载完)
Parse Stylesheet (解析5.css)
Evaluate Script (解析41.js)

代码二:

<script>标签后的css始终在<script>后解析,除非<script>标签被指定为defer或async属性。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>keepnight</title>
<link rel="stylesheet" type="text/css" href="5.css" />

<script src="41.js"></script>

<link rel="stylesheet" type="text/css" href="6.css" />
</head>
<body>

<h1>我的第一个 JavaScript 程序</h1>
<p>这是一个段落</p> 


</body>
</html>

1.第一种情况
同时对5.css,41.js,6.css发送请求,假设5.css先下载完,41.js后下载完,6.css最后下载完

上面的代码解析顺序为


Parse Stylesheet (解析5.css)
Parse Stylesheet (解析41.js)
Evaluate Script (解析6.css)

2.第二种情况
同时对5.css,41.js,6.css发送请求,假设5.css先下载完,6.css后下载完,41.js最后下载完。

上面的代码解析顺序为


Parse Stylesheet (解析5.css)
Parse Stylesheet (解析41.js)
Evaluate Script (解析6.css)

4.总结

(1)html文件可以边下载边解析
(2)css可以边下载边解析,css下载不会阻塞对dom的解析
(3)javascript下载完成才能解析,javascript下载和解析都会阻塞对dom的解析。但是浏览器采用推测性解析优化,可以在没有运行到<script src>之前下载javascript,这时不会阻塞dom的解析,相当于另起进程。
(4)css解析和javascript解析都会阻塞对dom的解析。
(5)css文件下载和解析不分先后,即谁先下载谁先解析。但是最后一个<link>标签决定展现你眼前的样式。
(6)<script>标签前的css文件一定在javascript执行前完成下载和解析,否则javascript会等待css文件下载和解析完才执行。
(7)<script>标签后的css文件一定在javascript执行后才能解析

文章目录