前端基础类库Arale的创始人淘宝玉伯定义的加载和阻塞三定律如下:
定律一:资源是否下载依赖 JS 执行结果——JS 有可能会修改 DOM。典型的,可能会有 document.write。这意味着,在当前 JS 加载和执行完成前,后续所有资源的下载有可能是没必要的。这是 JS 阻塞后续资源下载的根本原因。
定律二:JS 执行依赖 CSS 最新渲染——JS 的执行有可能依赖最新样式。比如,可能会有 var width = $('#id').width(). 这意味着,JS 代码在执行前,浏览器必须保证在此 JS 之前的所有 css(无论外链还是内嵌)都已下载和解析完成。这是 CSS 阻塞后续 JS 执行的根本原因。
定律三:现代浏览器存在 prefetch 优化—— 现代浏览器在竞争中,在 UI update 线程之外,还会开启另一个线程,对后续 JS 和 CSS 提前下载(注意,仅提前下载,并不执行)。有了 prefetch 优化,这意味着,在不存在任何阻塞的情况下,理论上 JS 和 CSS 的下载时机都非常优先,和位置无关。
根据三定律,我们认为:
一,如果真的需要把外联js和css放在head里,那也需要从下面这种排序
1. 外联js
2. 外联css
3. 外联js
统一为:
1. 外联css
2. 外联js
3. 外联js
不要script和css交替混编。
原因是,据有人称:
从Firefox 4+开始,对prefetch的策略有些许调整,调整在于 head 中 css 与 js 的位置。css 在外联 js 后面时,可能会在 script 后面的 css 加载好之前,提前进行首次渲染。然后等后面的 css 加载好后,再次更新 Render Tree 并进行渲染,造成页面闪烁现象。,各种优化策略,似乎随着浏览器版本不同,头可能发生细微差异。所以保守做法是,js 和 css 不要在 head 里交替混编,统一为先外联css再外联js!
二,但只有万不得已时,才会在 head 里放外联js,否则请把外联js放置到前。
原因是张克军的《js和css的顺序关系》指出:
只要 head 里出现外联js,无论如何放,css文件都不能和body里的请求并行。
body 里 dom 渲染取决于 head 里的js执行完。
外联js放在页面最后,高级浏览器会自动做优化(prefetch),你不用担心,它也可能会提前下载。