为什么link放在头部,script放在尾部?

1,372 阅读3分钟

面试过程对于浏览器的渲染可能经常会进行灵魂3问:

  1. script标签会阻塞页面渲染吗?
  2. link标签会阻塞页面渲染吗?
  3. 为什么link标签要放在文档头部(head),script标签要放在文档尾部?

今天,我们从浏览器的渲染原理出发,彻底搞明白为什么。

首先浏览器的渲染大致需要经过几个阶段,这里我直接放一张webkit渲染原理官方图说明一下

image.png

从图中可以看出,页面渲染需要经历html解析,css解析,js解释执行,layout布局,绘制几个阶段。今天我们讨论问题的答案就在html解析,css解析,js解释执行阶段

问题一:script标签会阻塞页面渲染吗?

答案是肯定的,js会阻塞页面渲染。在浏览器解析html文档的时候,遇到script标签时要等待script标签内容加载并执行完成,因为js可能会修改dom元素,如果先解析html在执行js,js中有修改dom的操作,那就需要重新解析,之前的解析就白做了。

问题二:link标签会阻塞页面渲染吗?

这里回答会或者不会都是不准确的,要分情况讨论,大致分为以下几种情况:

  • 情况一:当script标签和link标签都放在dom元素之前时,由于script会阻塞html解析,而script加载执行之前要求必须完成css加载(因为js可能会修改样式),从而导致了css阻塞解析的假象,实际还是js阻塞了html解析
  • 情况二:当只有link标签(或者script标签在dom元素之后),并且link标签在head(dom之前)时,css不会阻塞html解析,但是会阻塞dom绘制。浏览器在解析html之前会预解析html,找出html中的link,script等依赖项,link在dom之前,也就是说dom绘制依赖css样式,解析完html必须等css也解析完才能开始绘制,也就造成了css阻塞dom绘制;
  • 情况三:当只有link标签(或者script标签在dom元素之后),并且link标签在dom元素之后时,css样式对dom的绘制不会构成依赖,浏览器会先绘制dom,等css样式加载解析完成后,再次解析html,计算样式,进行重绘

问题三:为什么link标签要放在文档头部(head),script标签要放在文档尾部?

经过对上面两个问题的讨论,我们知道script标签会阻塞html解析,从而阻塞页面渲染,这是我们不想看到的,所以一般把script标签放在html文档的最后,或者给script标签加上defer,async参数,强制让script标签延迟加载

link标签不会阻塞html解析,如果link标签放在dom之后,会导致浏览器发生回流重绘,这个开销是非常大的,所以我们一般把link标签放在html文档开头(head)中