當你使用 Google PageSpeed Insights 或 Lighthouse 檢測網站時,經常會看到「排除禁止轉譯的資源」(Eliminate render-blocking resources)這項建議。這項優化對於提升網站的 首次內容繪製(FCP) 和 最大內容繪製(LCP) 至關重要。本文將深入探討什麼是禁止轉譯資源,以及如何有效排除它們來改善網站性能。
目錄
- 什麼是禁止轉譯資源?
- 為什麼需要排除禁止轉譯資源?
- 常見的禁止轉譯資源類型
- 檢測工具與分析方法
- 優化 CSS 的實用技巧
- 優化 JavaScript 的實用技巧
- 進階優化策略
- 實際案例與效果對比
- 常見問題與解答
什麼是禁止轉譯資源?
禁止轉譯資源(Render-Blocking Resources) 是指那些會阻止瀏覽器渲染頁面的外部資源,主要是 CSS 樣式表 和 JavaScript 腳本。
瀏覽器渲染流程
當瀏覽器載入網頁時,會依序執行以下步驟:
1. HTML 解析 → 建立 DOM 樹
↓
2. CSS 解析 → 建立 CSSOM 樹
↓
3. 合併 DOM + CSSOM → 渲染樹(Render Tree)
↓
4. 佈局(Layout)→ 計算元素位置
↓
5. 繪製(Paint)→ 顯示在螢幕上
問題所在:
- 瀏覽器遇到
<link rel="stylesheet">時,會暫停 HTML 解析,等待 CSS 下載並解析完成 - 瀏覽器遇到
<script>時,會暫停 HTML 解析,等待腳本下載並執行完成 - 這段等待時間就是「禁止轉譯」
視覺化說明
無優化情況:
HTML 解析 → [等待 CSS 下載] → [等待 JS 下載執行] → 渲染頁面
⬆ 阻塞點 ⬆ 阻塞點
用戶看到空白 用戶看到空白
優化後:
HTML 解析 → 渲染可見內容
⬆ CSS/JS 非阻塞載入
用戶立即看到內容
為什麼需要排除禁止轉譯資源?
📊 對性能指標的影響
| 指標 | 說明 | 影響程度 |
|---|---|---|
| FCP(首次內容繪製) | 用戶首次看到內容的時間 | ⭐⭐⭐⭐⭐ |
| LCP(最大內容繪製) | 最大內容元素渲染完成時間 | ⭐⭐⭐⭐⭐ |
| SI(速度指數) | 頁面可視區域填充速度 | ⭐⭐⭐⭐ |
| TTI(可互動時間) | 頁面完全可互動的時間 | ⭐⭐⭐⭐ |
📈 對業務的影響
根據 Google 的研究數據:
| 載入時間變化 | 跳出率變化 | 轉換率變化 |
|---|---|---|
| 1 秒 → 3 秒 | +32% | -20% |
| 1 秒 → 5 秒 | +90% | -45% |
| 1 秒 → 10 秒 | +123% | -60% |
✅ 優化後的好处
- 更快的首次渲染:用戶立即看到內容
- 更好的用戶體驗:減少白屏時間
- 更高的 SEO 排名:Core Web Vitals 是排名因素
- 更低的跳出率:用戶更願意等待
- 更高的轉換率:載入越快,轉換越高
常見的禁止轉譯資源類型
1️⃣ CSS 樣式表
阻塞原因: 瀏覽器需要 CSS 來計算樣式,無法在 CSS 載入前渲染頁面
常見情況:
<!-- 阻塞渲染 -->
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="framework.css">
<link rel="stylesheet" href="theme.css">
2️⃣ JavaScript 腳本
阻塞原因: JavaScript 可能修改 DOM,瀏覽器必須等待腳本執行完成
常見情況:
<!-- 阻塞渲染 -->
<script src="jquery.js"></script>
<script src="main.js"></script>
<script src="analytics.js"></script>
3️⃣ Web 字體
阻塞原因: 字體載入前的文字不可見(FOIT)或顯示備用字體(FOUT)
常見情況:
/* 可能導致渲染延遲 */
@font-face {
font-family: 'CustomFont';
src: url('font.woff2') format('woff2');
}
4️⃣ 第三方資源
常見阻塞來源:
- Google Analytics
- Facebook Pixel
- Google Ads
- 社交媒體按鈕
- 即時聊天工具
檢測工具與分析方法
🔍 Google PageSpeed Insights
網址: https://pagespeed.web.dev/
使用方式:
- 輸入網站網址
- 點擊「分析」
- 查看「排除禁止轉譯的資源」建議
解讀報告:
排除禁止轉譯的資源 估計可節省 1.2 秒
潛在的節省資源:
- /css/styles.css (節省 450ms)
- /js/main.js (節省 380ms)
- /css/framework.css (節省 370ms)
🔍 Chrome DevTools Lighthouse
開啟方式:
- 開啟網頁
- 按
F12開啟 DevTools - 切換到 Lighthouse 標籤
- 點擊「分析頁面載入效能」
優勢:
- 本地測試,無需上傳
- 可測試需要登入的頁面
- 提供詳細的水線圖(Waterfall)
🔍 Chrome DevTools Coverage
使用方式:
- 開啟 DevTools(F12)
- 按
Ctrl+Shift+P(Mac:Cmd+Shift+P) - 輸入「Coverage」並選擇 Show Coverage
- 點擊重新載入按鈕
功能: 顯示 CSS/JS 的使用率,找出未使用的程式碼
🔍 WebPageTest
網址: https://www.webpagetest.org/
優勢:
- 全球多地測試節點
- 詳細的水線圖分析
- 影片回放功能
- 可模擬不同網路速度
優化 CSS 的實用技巧
方法一:內聯關鍵 CSS(Critical CSS)
原理: 將首屏(Above the Fold)所需的 CSS 直接嵌入 HTML
實作:
<head>
<!-- 關鍵 CSS 內聯 -->
<style>
/* 首屏所需的樣式 */
body { font-family: Arial, sans-serif; margin: 0; }
.header { background: #333; color: white; }
.hero { height: 100vh; display: flex; align-items: center; }
</style>
<!-- 非關鍵 CSS 非同步載入 -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
工具推薦:
- Critical(npm 套件):自動提取關鍵 CSS
- Penthouse:基於 URL 的關鍵 CSS 生成
- Critters(Webpack 插件):自動內聯關鍵 CSS
使用 Critical 範例:
npm install critical
const critical = require('critical');
critical.generate({
inline: true,
base: 'dist/',
src: 'index.html',
dest: 'index.html',
minify: true,
width: 1920,
height: 1080
});
方法二:非同步載入 CSS
原理: 使用 preload 或 media 屬性避免阻塞
實作方式 A:preload + onload
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
實作方式 B:media 屬性
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
實作方式 C:JavaScript 動態載入
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'styles.css';
document.head.appendChild(link);
</script>
方法三:CSS 拆分與延遲載入
原理: 將 CSS 拆分為關鍵和非關鍵部分
實作:
<head>
<!-- 關鍵 CSS(內聯) -->
<style>/* 首屏樣式 */</style>
<!-- 非關鍵 CSS(非同步) -->
<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>
CSS 拆分策略:
/* critical.css - 首屏樣式 */
.header, .hero, .nav { ... }
/* non-critical.css - 其他樣式 */
.footer, .sidebar, .comments { ... }
方法四:移除未使用的 CSS
原理: 減少 CSS 檔案大小,加快載入速度
工具推薦:
- PurgeCSS:掃描 HTML/JS,移除未使用的 CSS
- UnCSS:類似 PurgeCSS
- Webpack + PurgeCSS:自動化流程
使用 PurgeCSS 範例:
npm install purgecss
const { PurgeCSS } = require('purgecss');
(async () => {
const purgeCSSResults = await new PurgeCSS().purge({
content: ['*.html', './src/**/*.js'],
css: ['*.css']
});
console.log(purgeCSSResults);
})();
效果: 通常可減少 70-90% 的 CSS 大小
優化 JavaScript 的實用技巧
方法一:使用 async 屬性
原理: 腳本非同步下載,下載完成後立即執行(不等待 HTML 解析)
實作:
<!-- 阻塞 -->
<script src="analytics.js"></script>
<!-- 非阻塞(推薦用於獨立腳本) -->
<script src="analytics.js" async></script>
適用場景:
- Google Analytics
- 廣告腳本
- 社交媒體按鈕
- 不依賴 DOM 的腳本
執行順序:
HTML 解析 → 遇到 <script async>
↓
非同步下載
↓
下載完成 → 立即執行
↓
HTML 解析繼續(可能被打斷)
方法二:使用 defer 屬性
原理: 腳本非同步下載,但等到 HTML 解析完成後才執行
實作:
<!-- 阻塞 -->
<script src="main.js"></script>
<!-- 非阻塞(推薦用於依賴 DOM 的腳本) -->
<script src="main.js" defer></script>
適用場景:
- 依賴 DOM 的腳本
- 需要按順序執行的腳本
- 主要的應用程式腳本
執行順序:
HTML 解析 → 遇到 <script defer>
↓
非同步下載
↓
HTML 解析完成 → 按順序執行
↓
DOMContentLoaded 事件
方法三:將腳本移至底部
原理: 將 <script> 標籤放在 </body> 之前
實作:
<body>
<!-- 頁面內容 -->
<div id="app">...</div>
<!-- 腳本放在底部 -->
<script src="main.js"></script>
</body>
優點:
- 簡單易用
- 無需修改腳本內容
缺點:
- 腳本下載仍會延遲
- 不如
defer現代化
方法四:代碼拆分(Code Splitting)
原理: 將大型腳本拆分為多個小塊,按需載入
Webpack 實作:
// 動態導入
const module = await import('./heavy-module.js');
// 或使用 magic comments
const module = await import(
/* webpackChunkName: "heavy-module" */
'./heavy-module.js'
);
效果:
- 初始載入更快
- 按需載入功能模組
- 改善快取效率
方法五:Tree Shaking
原理: 移除未使用的程式碼
Webpack 設定:
// webpack.config.js
module.exports = {
mode: 'production', // 自動啟用 Tree Shaking
optimization: {
usedExports: true, // 標記未使用的 exports
sideEffects: false // 標記無副作用的模組
}
};
套件設定(package.json):
{
"sideEffects": [
"*.css",
"*.scss"
]
}
進階優化策略
策略一:資源提示(Resource Hints)
preload: 預先載入當前頁面必需的資源
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">
prefetch: 預先載入下一頁可能需要的資源
<link rel="prefetch" href="next-page.js">
preconnect: 預先建立連線
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com">
dns-prefetch: 預先解析 DNS
<link rel="dns-prefetch" href="https://analytics.google.com">
策略二:服務_worker 快取
原理: 使用 Service Worker 快取資源,減少網路請求
基本實作:
// sw.js
const CACHE_NAME = 'v1';
const ASSETS = [
'/',
'/styles.css',
'/main.js',
'/font.woff2'
];
self.addEventListener('install', (e) => {
e.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS))
);
});
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then((response) => response || fetch(e.request))
);
});
註冊 Service Worker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
策略三:HTTP/2 與 HTTP/3
優勢:
- 多路復用(Multiplexing):單一連線傳輸多個資源
- 伺服器推送(Server Push):主動推送資源
- 標頭壓縮:減少傳輸大小
Nginx 設定:
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 啟用 HTTP/2 Push
http2_push /styles.css;
http2_push /main.js;
}
策略四:CDN 加速
推薦 CDN:
- Cloudflare:免費方案、全球節點
- Fastly:高性能、即時失效
- Akamai:企業級、最大網路
- AWS CloudFront:與 AWS 整合
優化效果:
- 減少延遲(更近的節點)
- 分擔源站負載
- 內建壓縮與優化
策略五:現代化構建工具
Vite: 基於 ESM 的現代構建工具
npm create vite@latest
優勢:
- 開發時無需打包
- 生產時使用 Rollup 優化
- 內建代碼拆分
- 更快的熱更新
實際案例與效果對比
案例一:電商網站首頁
優化前:
- FCP: 3.2 秒
- LCP: 4.8 秒
- 阻塞資源:8 個(5 CSS + 3 JS)
- 總大小:2.4 MB
優化措施:
- 內聯關鍵 CSS(節省 800ms)
- 非同步載入非關鍵 CSS(節省 600ms)
- 使用
defer載入 JS(節省 1.2 秒) - 移除未使用 CSS(減少 60% 大小)
- 啟用 CDN(減少 40% 延遲)
優化後:
- FCP: 1.1 秒(-66%)
- LCP: 1.8 秒(-63%)
- 阻塞資源:0 個
- 總大小:800 KB(-67%)
業務影響:
- 跳出率:-25%
- 轉換率:+18%
- 平均訂單金額:+12%
案例二:新聞媒體網站
優化前:
- FCP: 2.8 秒
- LCP: 4.2 秒
- 阻塞資源:6 個(4 CSS + 2 JS)
優化措施:
- 使用 Critical CSS
- 第三方腳本改用
async - 圖片延遲載入(Lazy Load)
- 啟用 HTTP/2
優化後:
- FCP: 0.9 秒(-68%)
- LCP: 1.5 秒(-64%)
- Google PageSpeed 分數:45 → 92
案例三:SaaS 應用後台
優化前:
- TTI: 5.6 秒
- 阻塞資源:12 個
優化措施:
- 代碼拆分(Code Splitting)
- 路由層級 lazy loading
- Tree Shaking
- Service Worker 快取
優化後:
- TTI: 1.8 秒(-68%)
- 阻塞資源:2 個
- 用戶滿意度:+35%
常見問題與解答
Q1:內聯 CSS 會增加 HTML 大小嗎?
答: 會,但只內聯關鍵 CSS(通常 10-15KB),遠小於完整 CSS 檔案。
最佳實踐:
- 只內聯首屏所需的 CSS
- 非關鍵 CSS 非同步載入
- 使用工具自動提取關鍵 CSS
Q2:async 和 defer 有什麼差別?
| 特性 | async | defer |
|---|---|---|
| 下載 | 非同步 | 非同步 |
| 執行時機 | 下載完成立即執行 | HTML 解析完成後執行 |
| 執行順序 | 不保證 | 按順序 |
| 適用場景 | 獨立腳本(如分析) | 依賴 DOM 的腳本 |
建議: 優先使用 defer,除非腳本完全獨立
Q3:如何處理第三方腳本的阻塞?
解決方案:
<!-- 方案 1:async -->
<script async src="https://www.googletagmanager.com/gtag/js"></script>
<!-- 方案 2:延遲載入 -->
<script>
setTimeout(() => {
const script = document.createElement('script');
script.src = 'https://third-party.js';
document.body.appendChild(script);
}, 3000);
</script>
<!-- 方案 3:使用者互動後載入 -->
<script>
document.addEventListener('click', () => {
const script = document.createElement('script');
script.src = 'https://chat-widget.js';
document.body.appendChild(script);
}, { once: true });
</script>
Q4:優化後樣式跑掉了怎麼辦?
可能原因:
- 關鍵 CSS 提取不完整
- CSS 載入順序錯誤
- specificity 改變
解決方案:
- 使用工具完整提取關鍵 CSS
- 確保非關鍵 CSS 在非同步載入後應用
- 測試不同視窗大小
測試清單:
- [ ] 桌面版(1920px)
- [ ] 平板版(768px)
- [ ] 手機版(375px)
- [ ] 滾動頁面檢查樣式
Q5:如何持續監控性能?
推薦工具:
- Google Search Console:Core Web Vitals 報告
- Chrome UX Report:真實用戶數據
- Web Vitals Library:前端監控
- Lighthouse CI:自動化測試
Web Vitals 監控實作:
import { onFCP, onLCP, onCLS } from 'web-vitals';
onFCP(console.log);
onLCP(console.log);
onCLS(console.log);
結論
排除禁止轉譯資源是提升網站性能的最有效方法之一。透過正確的優化策略,可以顯著改善用戶體驗、提高 SEO 排名,並帶來實際的業務成長。
快速開始清單
- 檢測:使用 PageSpeed Insights 找出阻塞資源
- CSS 優化:內聯關鍵 CSS + 非同步載入剩餘 CSS
- JS 優化:使用
defer或async - 移除冗餘:刪除未使用的 CSS/JS
- 監控:持續追蹤 Core Web Vitals 指標
優先順序建議
| 優先級 | 優化項目 | 預期效果 |
|---|---|---|
| 🔴 高 | 內聯關鍵 CSS | FCP -40% |
| 🔴 高 | JS 使用 defer/async | FCP -30% |
| 🟡 中 | 移除未使用 CSS | 大小 -60% |
| 🟡 中 | 代碼拆分 | TTI -40% |
| 🟢 低 | HTTP/2 Push | 延遲 -20% |
最終建議
- 從最影響的優化開始:關鍵 CSS + JS defer
- 測試每一個改動:確保功能正常
- 持續監控:性能優化是持續過程
- 平衡複雜度:不要過度優化
記住:最快的資源是無需載入的資源。優先考慮移除不必要的資源,其次才是優化載入方式。