非同步載入 CSS 的方式主要有以下幾種,它們的目的都是為了防止 CSS 阻塞渲染,提升頁面載入效能:
1. 使用 <link>
標籤的 media
屬性:
這是最簡單的一種非同步載入方式。透過設定一個不匹配的媒體查詢,瀏覽器會認為這個 CSS 檔案不重要,從而非同步載入。頁面載入完成後,再動態修改 media
屬性為匹配的查詢,使 CSS 生效。
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">
- 優點: 簡單易用,相容性好。
- 缺點: 會下載 CSS 檔案,但樣式應用會延遲到
onload
事件觸發,導致頁面閃爍 (FOUC - Flash of Unstyled Content)。
2. 使用 <link>
標籤的 rel="preload"
和 onload
事件:
這種方式利用 preload
預載入 CSS 檔案,並在載入完成後透過 JavaScript 將其新增到頁面。
<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="style.css"></noscript>
- 優點: 預載入可以提高載入優先順序,減少 FOUC。
noscript
標籤保證了在 JavaScript 禁用的情況下 CSS 仍然可以載入。 - 缺點: 稍微複雜一些,需要 JavaScript 程式碼。
3. 使用 JavaScript 動態插入 <link>
標籤:
這種方式完全透過 JavaScript 控制 CSS 的載入。
var link = document.createElement('link');
link.href = 'style.css';
link.rel = 'stylesheet';
document.head.appendChild(link);
- 優點: 靈活控制載入時機。
- 缺點: 需要 JavaScript 程式碼,如果執行時機不當,可能會阻塞渲染。
4. 使用 @import
規則 (不推薦):
@import
規則可以匯入外部 CSS 檔案。然而,它會阻塞頁面渲染,因此不推薦使用。
@import url("style.css");
- 缺點: 阻塞渲染,效能差。
5. 使用 Web Workers (較少使用):
Web Workers 可以在後臺執行緒載入 CSS,避免阻塞主執行緒。但是,由於 Web Workers 無法直接操作 DOM,因此需要透過postMessage與主執行緒通訊,實現起來比較複雜,實際應用較少。
最佳實踐建議:
- 對於非關鍵 CSS,推薦使用
rel="preload"
和onload
的組合方式,以獲得最佳效能和相容性。 - 對於關鍵 CSS,為了避免 FOUC,最好內聯到
<head>
中,或者使用 critical CSS 的技術,將首屏渲染所需的 CSS 內聯,其餘部分非同步載入。
選擇哪種方法取決於你的具體需求和專案情況。 優先考慮 media
和 preload
方法,它們相對簡單且有效。 避免使用 @import
。 Web Workers 適用於複雜場景,但需要謹慎使用。 最終目標是儘可能減少 CSS 對渲染的阻塞,提高使用者體驗。