新的思考.
- CSS和JS在網(wǎng)頁中的放置順序
- 白屏和FOUC
- async和defer的作用和區(qū)別
- 網(wǎng)頁的渲染機(jī)制
CSS和JS在網(wǎng)頁中的放置順序
通常情況,人們都會在
<head></head>
(Html頭部位置)里面以<link>
來引入** Css **文件...** JavaScript **則不同,視情況而定:
通常的做法是將 JavaScript 代碼放置在 HTML 文檔的<head></head>
標(biāo)簽之間产场。因為 HTML 文檔是由瀏覽器從上到下依次載入的侣颂,所以將 JavaScript 代碼放置于<head></head>
標(biāo)簽之間,可以確保在需要使用腳本之前,已經(jīng)被載入(最佳做法:只放置呈現(xiàn)頁面效果實現(xiàn)類的 javascript)奄薇。
另一種方法:將 JavaScript 代碼放置于 <body></body> 之間的菠赚。這樣做的目的脑豹,是考慮到如果我們有一段 JavaScript 代碼需要操作(動作、交互等) HTML 元素衡查。但由于 HTML 文檔是由瀏覽器從上到下依次載入的瘩欺,為避免 JavaScript 代碼操作 HTML 元素時,HTML 元素還未載入而報錯(對象不存在)拌牲,因此需要將這段代碼寫到 HTML 元素后面俱饿。
另外,運(yùn)用得最多的一種塌忽,是引用外部 script 的使用...跟引入外部 css 一個道理拍埠。
- 引用好處:
- 便于管理..
- 避免在 JavaScript 代碼里使用
- 避免使用難看的 CDATA
- 公共的 JavaScript 代碼可以被復(fù)用于其他 HTML 文檔,也利于 JavaScript 代碼的統(tǒng)一維護(hù)
- HTML 文檔更小土居,利于搜索引擎收錄
- 可以壓縮枣购、加密單個 JavaScript 文件
- 瀏覽器可以緩存 JavaScript 文件,減少寬帶使用(當(dāng)多個頁面同時使用一個 JavaScript 文件的時候擦耀,通常只需下載一次)
- 避免使用復(fù)雜的 HTML 實體棉圈,如可以直接使用 document.write(2>1) 而無需寫作 document.write(2<1)
將 JavaScript 代碼形成為外部文件,也會增加服務(wù)器的 HTTP 請求負(fù)擔(dān)眷蜓,在超高并發(fā)請求的環(huán)境下迄损,這并不是一個好的策略。另外 在引用外部 js 文件時账磺,需注意文件的正確路徑芹敌。
- 加載異步:
<script defer src="script.js"></script>
<script async src="script.js"></script>
defer和asnyc是腳本異步加載的兩種方式痊远。
defer,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步)氏捞,但 script.js 的執(zhí)行要在所有元素解析完成之后碧聪,DOMContentLoaded 事件觸發(fā)之前完成。
async液茎,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)逞姿。
白屏和FOUC
白屏和FOUC(無樣式內(nèi)容閃爍)的產(chǎn)生主要與瀏覽器的渲染機(jī)制有關(guān),有的瀏覽器是等待html和css全部加載完成后再進(jìn)行渲染(白屏問題)捆等,有的瀏覽器是先顯示已加載的html內(nèi)容滞造,等到css加載完成后重新對內(nèi)容添加樣式(FOUC問題)
白屏的產(chǎn)生
白屏的產(chǎn)生有三種情況:將css文件放在html文檔的最后、使用@import引入css(因為通過@import引入的css文件會被最后加載栋烤,因此也會導(dǎo)致白屏)或者將js文件放在頭部谒养,而未使用defer或async延遲或異步加載js文件,導(dǎo)致js阻塞html和css的加載原理分析:
對于-webkit內(nèi)核的瀏覽器(IE也會產(chǎn)生)明郭,在進(jìn)行網(wǎng)頁渲染時买窟,會同時加載html和css分別構(gòu)建DOM樹和CSSOM,等兩者都構(gòu)建完成后薯定,再繪制渲染樹始绍,然后將頁面顯示出來。如果在html中將css文件放置在文檔最后话侄,那么將會導(dǎo)致CSSOM晚于DOM樹的建立亏推,瀏覽器需要等待CSSOM建立,然后才進(jìn)行網(wǎng)頁內(nèi)容的繪制年堆,這個等待的過程吞杭,沒有內(nèi)容顯示,就導(dǎo)致了白屏的產(chǎn)生嘀韧,因此在開發(fā)中篇亭,需要將CSS放在head標(biāo)簽內(nèi),讓其與html內(nèi)容同時被加載锄贷。FOUC的產(chǎn)生
主要是由于瀏覽器先顯示已加載的html內(nèi)容译蒂,等到css加載完成后重新對內(nèi)容添加樣式導(dǎo)致的,主要代表有Firefox
async和defer的作用和區(qū)別
<pre><script src="script.js"></script>
</pre>
- 沒有 defer 或 async谊却,瀏覽器會立即加載并執(zhí)行指定的腳本柔昼,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說不等待后續(xù)載入的文檔元素炎辨,讀到就加載并執(zhí)行捕透。
<script async src="script.js"></script>
- 有 async,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)。
<script defer src="myscript.js"></script>
- 有 defer乙嘀,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步)末购,但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成虎谢。
然后從實用角度來說呢盟榴,首先把所有腳本都丟到 </body> 之前是最佳實踐,因為對于舊瀏覽器來說這是唯一的優(yōu)化選擇婴噩,此法可保證非腳本的其他一切元素能夠以最快的速度得到加載和解析擎场。
網(wǎng)頁的渲染機(jī)制
瀏覽器會解析這么三個東西:
一個是HTML/SVG/XHTML,解析他們會產(chǎn)生DOM tree
CSS文件几莽,構(gòu)建CSS Rule Tree(產(chǎn)生CSSOM:CSS object Model)
JavaScript腳本迅办,主要通過DOM API 和CSSOM API來操作DOM樹和CSS Rule Tree解析完成后,會通過DOM Tree和CSS Rule Tree來構(gòu)建
Rendering Tree章蚣,注意:Rendering Tree并不等同于DOM Tree站欺,因為像header和display:none相關(guān)的東西就沒有必要放在Rendering 渲染樹中了
CSS Rule Tree主要是為了將CSS Rule添加到Rendering Tree中的每一個element中,也就是DOM節(jié)點
然后計算每個DOM節(jié)點的位置究驴,這個過程叫做layout
最后將頁面繪制出來镊绪,呈現(xiàn)引擎會遍歷Rendering Tree匀伏,由用戶界面后端層將每個節(jié)點繪制出來洒忧。