JS、CSS 之间的顺序与 HTML 页面的性能关系
前言
HTML CSS JavaScript 可以算是前端必须掌握的东西了,但是我们的浏览器是怎样解析这些东西的呢 我们如何处理 HTML CSS JavaScript 这些东西来让我们的网页更加合理,在我这里做了一些实验,总结起来给大家看看。
最简单的页面
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<img src="download-button.png">
</body>
</html>
我们打开 chrome 的控制台查看 timeline
由上图 可得结论
- 图中蓝色透明条标识浏览器从发起请求到接收到服务器返回第一个字节的时间,时间还是挺长的,而蓝色实体条则为真正的html页面下载的时间 还是很短的。
- 图中红框内的这部分时间则表示浏览器从下载完成 html 之后开始构建 dom,当发现一个image标签时所花费的时间,由此可见dom是顺序执行的,当发现image时便立即发起请求,而紫色透明条则是image发起请求时在网络传输时所消耗的时间。
- 图中timeline蓝色竖线所处的时间为domComplete时间,红色竖线为 dom 的 onload 时间,由此可见两种事件的差异。而浏览器构建dom树所花费的时间可以算出即domComplete时间 减去 html下载完成后的时间大概80ms。
含有 css 的页面
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
</head>
<body>
<img src="download-button.png">
</body>
</html>
我们打开chrome的控制台查看timeline
在添加了外部引入css之后,并没有发现什么异常,但是有一点指的注意,也就是红色竖线和蓝色竖线挨得更进了,这表明domComplete时间必须等待css解析完成,也就是构建dom树必须等待css解析完成,这也就解释了下图
含有 javascript 和 css 的页面
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
</head>
<body>
<img src="download-button.png">
<script type="text/javascript" src="H5FullscreenPage.js"></script>
</body>
</html>
我们打开chrome的控制台查看timeline
- 图上显示在引入外部的js文件之后domComplete时间又被延后了,结合上面的renderTree,由于javascript代码可能会更改css属性或者是dom结构,所以在形成renderTree之前必须等待javascript解析完成才能接着构建renderTree。
- 将javascript放在head内和body底部的区别也在于此,放在head里面,由于浏览器发现head里面有javascript标签就会暂时停止其他渲染行为,等待javascript下载并执行完成才能接着往下渲染,而这个时候由于在head里面这个时候页面是白的,如果将javascript放在页面底部,renderTree已经完成大部分,所以此时页面有内容呈现,即使遇到javascript阻塞渲染,也不会有白屏出现。
内嵌 javascript 的页面
图上可以看到,由于内嵌了 javascript,页面上减少了一个请求,导致html文档变大,消耗时间增多,但是domComplete时间提升的并不多。
使用 async 的 javascript
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
</head>
<body>
<img src="download-button.png">
<script async src="H5FullscreenPage.js" type ="text/javascript" ></script >
</body>
</html>
- 可以看到domComplete时间被大大提前 javascript也没有阻塞css和body里面img元素的并行下载。
- 使用async标识的script,浏览器将异步执行这中script不会阻塞正常的dom渲染,这时html5所支持的属性,另外defer也可以达到这种效果。
head 里面 js 和 css 加载的关系
外联 js 在 css 前面
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script src="H5FullscreenPage.js" type ="text/javascript" ></script >
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
</head>
<body>
<img src="download-button.png">
</body>
</html>
没有阻止 css 的并行加载但是影响了 body 里面 img 的并行加载
外联 js 在 css 中间
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<script src="H5FullscreenPage.js" type ="text/javascript" ></script >
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
</head>
<body>
<img src="download-button.png">
</body>
</html>
影响了 css 的并行加载和 body 里面 img 的并行加载
外联 js 在 css 最后
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
<script src="H5FullscreenPage.js" type ="text/javascript" ></script >
</head>
<body>
<img src="download-button.png">
</body>
</html>
影响了css 的并行加载和 body 里面 img 的并行加载
内嵌 js 在 css 前面
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script type ="text/javascript" >
var f = 1;
f++;
</script >
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
</head>
<body>
<img src="download-button.png">
</body>
</html>
没有影响 css 的并行加载也没有影响 body 里面 img 的并行加载
内嵌 js 在 css 中间
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<script type ="text/javascript" >
var f = 1;
f++;
</script >
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
</head>
<body>
<img src="download-button.png">
</body>
</html>
影响了css的并行加载没有英雄body里面img的并行加载
内嵌 js 在 css 最后
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="page-animation.css" media="screen">
<script type ="text/javascript" >
var f = 1;
f++;
</script >
</head>
<body>
<img src="download-button.png">
</body>
</html>
影响了css和body里面img的并行加载。
综上所述
当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用了CSS或者 IMAGE,就会再发1个 request 去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回 后,只需要把返回的内容放入到 DOM 树中对应的位置就 OK。但当引用了 JS 的时候,浏览器发送1个 js request 就会一直等待该request的返回。因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现。
这里的结论:
- 在 head 里面尽量不要引入 javascript。
- 如果要引入 js 尽量将 js 内嵌。
- 把内嵌 js 放在所有 css 的前面。
后记
- 本次的测试页面 http://1.lvming6816077.sinaapp.com/testaa/demo.html
- 测试所用浏览器 chrome
- 参考资料:
- 如果有哪里说的不清楚或者错误的地方,欢迎留言反馈。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论