关于外部样式表的阻塞问题
外部样式表会不会阻塞文档解析?
不会。
style-sheets 不会修改 DOM 树,没有理由为了解析 style-sheets 而阻塞文档解析(即 style-sheets 不会阻塞文档解析)。但如果在解析文档过程中有脚本需要访问样式信息时,为了保证访问样式信息的正确性。Firefox 会阻塞所有脚本直到 style-sheets 下载解析完为止。而 WebKit 只在访问的样式属性没有被加载解析时,才会阻塞脚本。
即 style-sheet 不会直接阻塞文档解析,它只阻塞 script 的解析执行,才导致 style-sheet 间接阻塞文档解析。
总结
- style-sheet 默认情况下是不会阻塞文档解析。
- style-sheet 只会阻塞 script 脚本解析执行。
关于 Script 的加载顺序
使用方式
-
内嵌 JS 代码
<script> function sayScript() { alert("<\/script>"); } </script> 复制代码
注意:在标签内写代码时,不能出现字符串"",如果要用,也只能通过转义来解决。
-
引用外部文件
<script src="example.js"></script> // OR <script src="example.js" /> 复制代码
注意:
<script>
默认type
就是 "text/javascript"。因此无需显示写出来。
加载顺序
在解释 <script>
内的代码时,页面中其他内容都不会被浏览器加载或显示。同样,在下载外部文件和解析外部文件时,页面的处理会暂时停止。注意,script 的特性是加载了并执行里面的脚本,然后再加载并执行下一个 script。
只要不存在 defer
和 async
属性,浏览器都会按照 <script>
元素在页面中出现的先后顺序对它们依次进行解析。
浏览器是单进程执行 JS 和加载 JS 的,并且解析 HTML 也是单进程的,是阻塞的。直观的感受有,弹窗时页面会“卡住”,加载时页面会白屏。
为什么需要顺序加载和执行?
因为 JS 有可能修改 DOM,如果不阻塞后续的资源下载,DOM 的操作顺序不可控。
如何降低这种阻塞的影响?
可以将 <script>
放在 <body>
的最后。一方面,这样可以使页面尽快渲染;另一方面,在 DOM 结构生成之前操作 DOM,可能会报错。
defer 和 async
补充:当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。
初步理解
-
defer
英语的意思就是推迟,延迟。那么顾名思义,就是延迟脚本执行的意思。脚本会被延迟到整个页面解析完再运行。
相当于告诉浏览器:立即下载,但是延迟执行。
-
async
目的是不让页面等待脚本下载和执行,而是异步加载页面其他内容。
属性效果
二者都会并行下载,不会影响页面的解析。
defer
会按照顺序在 DOMContentLoaded 前按照页面出现顺序依次执行。async
下载完立即执行。不保证按照指定的先后顺序执行。
进一步理解
-
defer
可以认为是将外链的js放在了页面底部。js的加载不会阻塞页面的渲染和资源的加载。不过defer会按照原本的js的顺序执行,所以如果前后有依赖关系的js可以放心使用。 -
async
能够异步的加载和执行脚本,不因为加载脚本而阻塞页面的加载。一旦加载到就会立刻执行在有async的情况下,js一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就很有可能出错。另外,建议异步脚本不要在加载期间修改 DOM。
参考
-
《JavaScript 高级程序设计》(第3版)
-
《彻底搞懂 async & defer》github.com/xiaoyu2er/b…