前端性能優化 css和js的加載與執行


一個網站在瀏覽器端是如何進行渲染的?
html本身首先會被渲染成 DOM 樹,實際上 html 是最先通過網址請求過來的,請求過來之后,html 本身會由一個字節流轉化成一個字符流,瀏覽器端拿的就是字符流,然后通過詞法分析之后,將相應的語法分析成相應的 token ,比如說 header token, 轉化不同的 token tag ,然后通過 token 類型 append 到 dom 樹。
遇到 link token tag,然后去請求 css ,請求過來之后再去對 css 進行解析,生成 CSSOM ,然后和 DOM 樹進行結合形成 Render Tree 這樣的渲染樹。然后再進行布局和渲染。
遇到 script tag ,然后去請求 JS 相關的 web 資源,請求回來的 js 會交給瀏覽器的 v8 引擎進行解析,

HTML渲染過程的一些特點
1、順序執行
因為他是使用詞法分析的能力,從上到下依次分析整個html,tag 相應的情況,所以第一個特點是順序執行。詞法分析是對 html 這個文檔解析的一個方式,對 tag 依次從上到下解析,這個從上到下決定了很多阻塞的情況。
2、並發加載
我們的html中可能會引入很多的 css,js 的 web 資源,這些 web 資源在瀏覽器端是並發加載的,這里需要優化的一點就是這個並發加載過程的並發度是受我們瀏覽器域名限制的。所以會設置 3 到 4 個 CDN 域名,防止單個域名的限制

3、是否阻塞
首先 css 的加載是否會阻塞 js 的加載,js 的加載是否阻塞 js 的執行, css 的加載是否會阻塞頁面的渲染。
css 在 head 中通過 link 方式引入的話,他會阻塞頁面的渲染。就是要等這個 css 加載完之后才會進行渲染。所以這個時候分析完之后是帶樣式的,所以推薦是放在 head 里面請求 css

css 通過 link 的方式,css會阻塞頁面的渲染,css 會阻塞 js 的執行,因為 js 會影響樣式,js 的執行會依賴一些 css 的屬性,如果 css 沒有加載完,可能會有問題。但 css 不阻塞外部腳本的加載,原因是 webkit 實際上有一個預先掃描器,他是可以預先掃描后面的詞語的,所以他不會阻止加載的過程,但會阻止執行的過程。
直接引入的js會阻塞頁面的渲染,因為 js 的執行會影響 dom 節點的修改,所以會阻塞后面的節點創建。這也是符合邏輯的。

4、依賴關系
html渲染過程中,是否有要遵循的依賴關系,如何保證依賴關系正確的情況下提高效率。比如有些情況 html 已經出來了,但是樣式沒有,然后突然閃了一下,樣式出來了。這種情況就是沒有遵循依賴關系,一般 css 放在 head tag 里面,頁面就會等 css 加載好,生成 cssom ,再進行渲染,這個時候就不會出現 css 閃動的問題。有時候 js 會加 async,這個時候就是放棄的 js 的依賴關系,這時候需要關注js的依賴關系

頁面渲染依賴於 css 的加載
js 的執行順序的依賴關系
js 邏輯對於 dom 節點的依賴關系,有些 js 需要去獲取 dom 節點


5、引入方式
比如是 link 引入,還是 import 引入,兩者有什么區別。對於js,比如 tag,比如動態引入。

直接引入,會阻塞頁面的渲染
defer,不會阻塞頁面的渲染,在 defer 的時候,所有 dom 樹都已經構建完成了。defer 是順序執行
async,不會阻塞頁面的渲染,跟 defer 不同的是,不保證執行順序,哪個先從服務端回來,哪個先執行
異步動態引入js,需要的時候,動態引入新的js文件,spa 單頁頁面中非常廣泛

根據這些特點,我們找到可以優化的點
1、css 樣式表置頂
2、用 link 代替 import,指的是 css 里面的 import,這個 import 是寫在最底層,這樣引入 css 的時候是不好的
3、js 腳本置底,並發請求的時候不區分 css 和 js 的,js 寫在頂部會影響 css 的加載,在渲染的時候,css 是由於 js的,所以跟頁面渲染無關的 js 放於頁面底部
4、合理使用 js 的異步加載能力,優化js的加載執行


實戰
1、加載並發數是有上限的,js和css混合放置,會導致css的延遲,會導致頁面閃動,所以js要置底
2、css放在header中,阻塞頁面的渲染,css加載完,再加載dom,放置頁面樣式跳變,從而保證渲染一步到位
3、css不會阻塞后面js並發加載,但會阻塞js的執行。如果js放在header中,會阻塞html的渲染。

4、把js都放在header, 分別放 async,defer。
async 不阻塞頁面渲染,不保證執行順序,誰先回來誰執行,不保證dom書構造完成之后再執行。
defer 不阻塞頁面渲染, 保證執行順序,保證dom樹構造完成之后再執行。

5、@import link 實操
@import 有兩個重大缺陷,第一點它不支持並發執行。他要 import 之后,再去 import 第二個,他不支持並發。
第二點,他需要整個頁面全部加載完之后,才去執行 import 里面的代碼。

但是,,,可能這兩個重大缺陷曾經存在過,但是現在這兩個問題已經沒有了,跟 link 的效果是一模一樣的。他更適合用於 css 模塊化。但是在不同 css 文件中 @import 的是不支持並發的,只有該 css 文件加載完之后才去加載 @import 里面的 css


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM