浏览器页面加载过程
1、打开网页的时候,浏览器会从服务器获取到HTML内容
2、浏览器获取到HTML内容后,就开始从上往下解析HTML的元素
3、 <head>元素内容会被先解析,此时浏览器还没有开始渲染页面
4、当浏览器解析到第三步时候,会暂停解析并下载js脚本
5、当js基本下载完成后,浏览器的控制权就转交给javascript引擎。当脚本执行完成后,控制权会交回渲染引擎,渲染引擎会继续往下解析HTML页面
6、此时,<body>元素内容开始被解析,浏览器开始渲染页面
在这个过程中,我们看到`<head>`中放置的`<script>`元素会阻塞页面的渲染过程:把 JavaScript 放在
<head>里,意味着必须把所有 JavaScript 代码都下载、解析和解释完成后,才能开始渲染页面。
到这里,我们就明白了:如果外部脚本加载时间很长(比如一直无法完成下载),就会造成网页长时间失去响
应,浏览器就会呈现“假死”状态,用户体验会变得很糟糕。
因此,对于对性能要求较高、需要快速将内容呈现给用户的网页,常常会将 JavaScript 脚本放在<body>的
最后面。这样可以避免资源阻塞,页面得以迅速展示。我们还可以使用defer/async/preload`等属性来
标记<script>标签,来控制 JavaScript 的加载顺序。
- defer: 异步下载,HTML解析完成后执行,最迟也会在DOMContentLoaded事件前执行完
- async: 下载会在加载完JS后立即执行,最迟也会在load事件前执行完
- preload: 预加载,一旦启用后便会告知浏览器应该尽快的加载某个资源。
- <link rel="preload" as="script" href="foo.js">
- <link rel="preload" as="style" href="bar.css">
如果你的脚本依赖于DOM构建完成是否完成,则可以使用defer;如果无需DOM的构建,那就可以放心的使用async了