hello~各位親愛的看官老爺們大家好。 估計大家都聽過, 儘量將 CSS 放頭部, JS 放底部, 這樣可以提高頁面的性能。 然而, 為什麼呢?大家有考慮過麼?很長一段時間,
友情提示, 本文也是小白向為主, 如果直接想看結論可以拉到最下面看的~
推薦下我的前端群:524262608, 不定期分享乾貨, 包括我自己整理的一份2017最新的前端資料和零基礎入門教程, 歡迎初學和進階中的小夥伴。
由於關係到檔的讀取, 那是肯定需要伺服器的, 我會把全部的檔放在 github 上, 給我點個 star 我會開心!掘金上再給我點個 贊 我就更開心了~
node 端唯一需要解釋一下的是這個函數:
function sleep(time) { return new Promise(function(res) {setTimeout(() => {res()}, time);})}嗯!其實就延時啦。 如果 CSS 或者 JS 檔案名有 sleep3000 之類的首碼時, 意思就是延遲3000毫秒才會返回這檔。
下文使用的 HTML 檔是長這樣的:
我會在其中插入不同的 JS 和 CSS 。
而使用的 common.css , 不論有沒有首碼, 內容都是這樣的:
div { background: red;}好了, 話不多數, 開始正文!
關於 CSS , 大家肯定都知道的是 標籤放在頭部性能會高一點, 少一點人知道如果 , JS 檔的內容是:
const div = document.querySelecot('div');console.log(div);defer 屬性相信大家也很熟悉了, MDN對此的描述是用來通知流覽器該腳本將在文檔完成解析後, 觸發 DOMContentLoaded 事件前執行。 設置這個屬性, 能保證 DOM 解析後馬上列印出 div 。
之後將 插入 HTML 檔的任一位置, 打開流覽器, 可以看到是首先列印出 div 這個 DOM 節點, 過3s左右之後才渲染出一個淺藍色的 div 。
這裡簡單說一下, 流覽器是解析 DOM 生成 DOM Tree , 結合 CSS 生成的 CSS Tree , 最終組成 render tree , 再渲染頁面。 由此可見, 在此過程中 CSS 完全無法影響 DOM Tree , 因而無需阻塞 DOM 解析。 然而, DOM Tree 和 CSS Tree 會組合成 render tree , 那 CSS 會不會頁面阻塞渲染呢?
CSS 阻塞頁面渲染其實這一點, 剛才的例子已經說明了, 如果 CSS 不會阻塞頁面阻塞渲染, 那麼 CSS 檔下載之前, 流覽器就會渲染出一個淺綠色的 div , 之後再變成淺藍色。 流覽器的這個策略其實很明智的, 想像一下, 如果沒有這個策略, 頁面首先會呈現出一個原始的模樣, 待 CSS 下載完之後又突然變了一個模樣。 用戶體驗可謂極差, 而且渲染是有成本的。
因此, 基於性能與使用者體驗的考慮, 流覽器會儘量減少渲染的次數, CSS 順理成章地阻塞頁面渲染。
然而, 事情總有奇怪的, 請看這例子, HTML 頭部結構如下:
但思考一下這會產生什麼結果呢?
答案是流覽器會轉圈圈三秒, 但此過程中不會列印任何東西, 之後呈現出一個淺藍色的 div , 再列印出 null 。 結果好像是 CSS 不單阻塞了頁面渲染, 還阻塞了 DOM 的解析啊!稍等, 在你打算掀桌子瘋狂吐槽我之前, 請先思考一下是什麼阻塞了 DOM 的解析, 剛才已經證明了 CSS 是不會阻塞的, 那麼阻塞了頁面解析其實是 JS !但明明 JS 的代碼如此簡單, 肯定不會阻塞這麼久, 那就是 JS 在等待 CSS 的下載, 這是為什麼呢?
仔細思考一下, 其實這樣做是有道理的, 如果腳本的內容是獲取元素的樣式,
所以, 看官大人明白為何