首先,浏览器在加载页面的时候,会用到GUI渲染线程(渲染浏览器HTML元素)和Javascript引擎线程(处理Javascript脚本程序),由于Javascript在执行过程中可能会改变页面结构和样式,因此二者之间被设计为互斥的关系,也就是说当Javascript引擎执行时,GUI线程会被挂起。
具体加载过程如下:
-
当打开一个官网的时候,浏览器会从服务器中获取到HTML内容;
-
浏览器从上到下解析HTML元素,<head>标签内容会先被解析,此时浏览器还没开始渲染页面;
-
<head>标签若包含<script>标签,script元素通过src属性指向外部资源,当浏览器解析到这里时,会暂停解析并下载Javascript脚本;
-
Javascript脚本下载完成后,浏览器的控制权转交给Javascript引擎;
-
当脚本执行完成后,控制权会转交给渲染引擎;
-
此时<body>元素内容开始被解析,浏览器开始渲染页面;
我们可以看到<head>标签里的script元素会阻塞页面的渲染,如果外部脚本加载时间很长,就会造成网页长时间失去响应,浏览器就会呈现“假死”状态,这也就是为什么我们通常将Javascript脚本放在<body>的后面的原因。 当然,我们也可以使用defer/async/preload等属性来标记script标签,来控制Javascript的加载顺序。