CSS和JS在网页中的放置顺序是怎样的?
一般将CSS文件放在header内,页面渲染时先生成DOM树再根据CSS文件渲染树,如果CSS文件放在尾部会造成闪跳或者布局很乱很丑直到CSS加载完毕;
JS文件放在body尾部,因为如果按照传统将JS文件也放在header内,那么浏览器自上而下的执行代码到js文件会将所有的JS代码下载执行完毕后才会呈现页面的内容,这会导致让用户感到非常卡顿。所以一般我们将JS文件放在body的尾部。并且我们通常引入外部引入JS文件而并非内部嵌入代码,这样做的好处有以下三点:
- 可维护性
- 可缓存
- 适应未来
注:外部引入的JS文件script标签内不允许再写入其他代码。
解释白屏和FOUC
FOUC(无样式内容闪烁)和白屏出现的主要原因是不同浏览器加载渲染页面机制的不同所造成的。
有的是等待CSS加载完成之后,对HTML元素进行渲染和展示(白屏问题),如果把样式放在底部,对于IE浏览器以及Chrome,在某些场景下(新窗口打开,刷新等)页面会出现白屏,而不是内容逐步展现;如果使用 @import 标签,即使 CSS 放入 link, 并且放在头部,也可能出现白屏。PS:加载 JavaScript 时,会禁用并发,并且阻止其他内容的下载. 所以把 JavaScript 放入页面顶部也会导致白屏现象.。
有的是先对HTML元素进行展示,然后等待CSS加载完成之后重新对样式进行修改(FOUC无样式内容闪烁)。如果把样式放在底部,对于IE浏览器,在某些场景下(点击链接,输入URL,使用书签进入等),会出现 FOUC 现象(逐步加载无样式的内容,等CSS加载后页面突然展现样式).对于 Firefox 会一直表现出 FOUC .
为了解决白屏和FOUC,我们一般将CSS放在head标签里面。
async和defer的作用是什么?有什么区别?
当浏览器遇到script脚本时:
- <script src = 'script.js'></script>如果没有async或defer,那么浏览器会解析并执行script,并且在执行完之前都不会执行下面的代码。
- <script async src = 'script.js'></script>:表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效,也就是说解析执行的过程会和加载并渲染后续文档元素的过程同时进行(异步),但若有多个标记为async 的脚本并不保证按照指定它们的先后顺序执行。
-
<script defer src = 'script.js'></script>:表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。IE7 及更早版本对嵌入脚本也支持这个属性。意思是如果有defer那么脚本的加载会和后续元素的加载同时进行(异步),但该脚本会在所有元素解析完成后才会执行,并且在DOMContentLoaded事件触发前。(PS红宝书中说的现实中延迟脚本不一定按顺序执行,也不一定在DOMContentLoaded事件触发前执行,最好只包含一个延迟脚本)。
图中绿色线代表HTML解析,蓝色线表示网络读取,红色线代表执行时间。defer和async的区别在于script下载完何时执行;图中未说明defer是按照加载顺序执行的;async是乱序执行的,不管你声明的顺序如何只要它加载完了就会立刻执行。