web-performance-optimization

web-performance-optimization

熱門

最佳化網站與網頁應用程式的效能,包括載入速度、Core Web Vitals、打包大小、快取策略及執行時期效能

4.4萬星標
6503分支
更新於 2026/7/29
SKILL.md
readonlyread-only
name
web-performance-optimization
description

最佳化網站與網頁應用程式的效能,包括載入速度、Core Web Vitals、打包大小、快取策略及執行時期效能

網頁效能最佳化

概述

協助開發者最佳化網站與網頁應用程式的效能,以提升使用者體驗、SEO 排名與轉換率。此技能提供系統化的方法來測量、分析並改善載入速度、執行時期效能及 Core Web Vitals 指標。

何時使用此技能

  • 當網站或應用程式載入緩慢時
  • 當要針對 Core Web Vitals(LCP、FID、CLS)進行最佳化時
  • 當要減少 JavaScript 打包大小時
  • 當要改善可互動時間(TTI)時
  • 當要最佳化圖片與資源時
  • 當要實作快取策略時
  • 當要除錯效能瓶頸時
  • 當要準備效能稽核時

運作方式

步驟 1:測量當前效能

我會協助你建立基準指標:

  • 執行 Lighthouse 稽核
  • 測量 Core Web Vitals(LCP、FID、CLS)
  • 檢查打包大小
  • 分析網路瀑布圖
  • 找出效能瓶頸

步驟 2:找出問題

分析效能問題:

  • 大型 JavaScript 打包
  • 未最佳化的圖片
  • 阻擋渲染的資源
  • 伺服器回應時間過慢
  • 缺少快取標頭
  • 版面位移
  • 阻塞主執行緒的長時間任務

步驟 3:排定最佳化優先順序

專注於高影響力的改善:

  • 關鍵渲染路徑最佳化
  • 程式碼分割與延遲載入
  • 圖片最佳化
  • 快取策略
  • 第三方腳本最佳化

步驟 4:實作最佳化

套用效能改善:

  • 最佳化資源(圖片、字型、CSS、JS)
  • 實作程式碼分割
  • 加入快取標頭
  • 延遲載入非關鍵資源
  • 最佳化關鍵渲染路徑

步驟 5:驗證改善成果

測量變更的影響:

  • 重新執行 Lighthouse 稽核
  • 比較前後指標
  • 監控真實使用者指標(RUM)
  • 在不同裝置與網路上測試

範例

範例 1:最佳化 Core Web Vitals

## 效能稽核結果

### 當前指標(最佳化前)
- **LCP(最大內容繪製):** 4.2s ❌(應小於 2.5s)
- **FID(首次輸入延遲):** 180ms ❌(應小於 100ms)
- **CLS(累計版面位移):** 0.25 ❌(應小於 0.1)
- **Lighthouse 分數:** 62/100

### 發現的問題

1. **LCP 問題:** 主視覺圖片(2.5MB)載入緩慢
2. **FID 問題:** 大型 JavaScript 打包(850KB)阻塞主執行緒
3. **CLS 問題:** 未指定尺寸的圖片導致版面位移

### 最佳化計畫

#### 修正 LCP(最大內容繪製)

**問題:** 主視覺圖片為 2.5MB 且載入緩慢

**解決方案:**
\`\`\`html
<!-- 最佳化前:未最佳化的圖片 -->
<img src="/hero.jpg" alt="Hero">

<!-- 最佳化後:使用現代格式 -->
<picture>
  <source srcset="/hero.avif" type="image/avif">
  <source srcset="/hero.webp" type="image/webp">
  <img 
    src="/hero.jpg" 
    alt="Hero"
    width="1200" 
    height="600"
    loading="eager"
    fetchpriority="high"
  >
</picture>
\`\`\`

**額外最佳化:**
- 壓縮圖片至小於 200KB
- 使用 CDN 加速傳遞
- 預載主視覺圖片:`<link rel="preload" as="image" href="/hero.avif">`

#### 修正 FID(首次輸入延遲)

**問題:** 850KB JavaScript 打包阻塞主執行緒

**解決方案:**

1. **程式碼分割:**
\`\`\`javascript
// 最佳化前:所有內容在同一個打包中
import { HeavyComponent } from './HeavyComponent';
import { Analytics } from './analytics';
import { ChatWidget } from './chat';

// 最佳化後:延遲載入非關鍵程式碼
const HeavyComponent = lazy(() => import('./HeavyComponent'));
const ChatWidget = lazy(() => import('./chat'));

// 頁面可互動後再載入分析工具
if (typeof window !== 'undefined') {
  window.addEventListener('load', () => {
    import('./analytics').then(({ Analytics }) => {
      Analytics.init();
    });
  });
}
\`\`\`

2. **移除未使用的相依套件:**
\`\`\`bash
# 分析打包
npx webpack-bundle-analyzer

# 移除未使用的套件
npm uninstall moment  # 改用 date-fns(較小)
npm install date-fns
\`\`\`

3. **延遲非關鍵腳本:**
\`\`\`html
<!-- 最佳化前:阻擋渲染 -->
<script src="/analytics.js"></script>

<!-- 最佳化後:延遲執行 -->
<script src="/analytics.js" defer></script>
\`\`\`

#### 修正 CLS(累計版面位移)

**問題:** 未指定尺寸的圖片導致版面位移

**解決方案:**
\`\`\`html
<!-- 最佳化前:無尺寸 -->
<img src="/product.jpg" alt="Product">

<!-- 最佳化後:指定尺寸 -->
<img 
  src="/product.jpg" 
  alt="Product"
  width="400" 
  height="300"
  style="aspect-ratio: 4/3;"
>
\`\`\`

**針對動態內容:**
\`\`\`css
/* 為後續載入的內容保留空間 */
.skeleton-loader {
  min-height: 200px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}

@keyframes loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
\`\`\`

### 最佳化後結果

- **LCP:** 1.8s ✅(改善 57%)
- **FID:** 45ms ✅(改善 75%)
- **CLS:** 0.05 ✅(改善 80%)
- **Lighthouse 分數:** 94/100 ✅

範例 2:減少 JavaScript 打包大小

## 打包大小最佳化

### 當前狀態
- **總打包大小:** 850KB(gzip 後:280KB)
- **主要打包:** 650KB
- **第三方打包:** 200KB
- **載入時間(3G):** 8.2s

### 分析

\`\`\`bash
# 分析打包組成
npx webpack-bundle-analyzer dist/stats.json
\`\`\`

**發現:**
1. Moment.js:67KB(可用 date-fns 取代:12KB)
2. Lodash:72KB(使用整個函式庫,但只需要 5 個函式)
3. 未使用的程式碼:約 150KB 的無效程式碼
4. 無程式碼分割:所有內容在同一個打包中

### 最佳化步驟

#### 1. 取代重量級相依套件

\`\`\`bash
# 移除 moment.js(67KB)→ 使用 date-fns(12KB)
npm uninstall moment
npm install date-fns

# 最佳化前
import moment from 'moment';
const formatted = moment(date).format('YYYY-MM-DD');

# 最佳化後
import { format } from 'date-fns';
const formatted = format(date, 'yyyy-MM-dd');
\`\`\`

**節省:** 55KB

#### 2. 選擇性使用 Lodash

\`\`\`javascript
// 最佳化前:匯入整個函式庫(72KB)
import _ from 'lodash';
const unique = _.uniq(array);

// 最佳化後:只匯入需要的部分(5KB)
import uniq from 'lodash/uniq';
const unique = uniq(array);

// 或使用原生方法
const unique = [...new Set(array)];
\`\`\`

**節省:** 67KB

#### 3. 實作程式碼分割

\`\`\`javascript
// Next.js 範例
import dynamic from 'next/dynamic';

// 延遲載入重量級元件
const Chart = dynamic(() => import('./Chart'), {
  loading: () => <div>載入圖表中...</div>,
  ssr: false
});

const AdminPanel = dynamic(() => import('./AdminPanel'), {
  loading: () => <div>載入中...</div>
});

// 基於路由的程式碼分割(Next.js 自動處理)
// pages/admin.js - 僅在造訪 /admin 時載入
// pages/dashboard.js - 僅在造訪 /dashboard 時載入
\`\`\`

#### 4. 移除無效程式碼

\`\`\`javascript
// 在 webpack.config.js 中啟用 tree shaking
module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
    sideEffects: false
  }
};

// 在 package.json 中
{
  "sideEffects": false
}
\`\`\`

#### 5. 最佳化第三方腳本

\`\`\`html
<!-- 最佳化前:立即載入 -->
<script src="https://analytics.com/script.js"></script>

<!-- 最佳化後:頁面可互動後再載入 -->
<script>
  window.addEventListener('load', () => {
    const script = document.createElement('script');
    script.src = 'https://analytics.com/script.js';
    script.async = true;
    document.body.appendChild(script);
  });
</script>
\`\`\`

### 結果

- **總打包大小:** 380KB ✅(減少 55%)
- **主要打包:** 180KB ✅
- **第三方打包:** 80KB ✅
- **載入時間(3G):** 3.1s ✅(改善 62%)

範例 3:圖片最佳化策略

## 圖片最佳化

### 當前問題
- 15 張圖片總計 12MB
- 未使用現代格式(WebP、AVIF)
- 無響應式圖片
- 無延遲載入

### 最佳化策略

#### 1. 轉換為現代格式

\`\`\`bash
# 安裝圖片最佳化工具
npm install sharp

# 轉換腳本(optimize-images.js)
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');

async function optimizeImage(inputPath, outputDir) {
  const filename = path.basename(inputPath, path.extname(inputPath));
  
  // 產生 WebP
  await sharp(inputPath)
    .webp({ quality: 80 })
    .toFile(path.join(outputDir, \`\${filename}.webp\`));
  
  // 產生 AVIF(最佳壓縮)
  await sharp(inputPath)
    .avif({ quality: 70 })
    .toFile(path.join(outputDir, \`\${filename}.avif\`));
  
  // 產生最佳化的 JPEG 備用
  await sharp(inputPath)
    .jpeg({ quality: 80, progressive: true })
    .toFile(path.join(outputDir, \`\${filename}.jpg\`));
}

// 處理所有圖片
const images = fs.readdirSync('./images');
images.forEach(img => {
  optimizeImage(\`./images/\${img}\`, './images/optimized');
});
\`\`\`

#### 2. 實作響應式圖片

\`\`\`html
<!-- 使用現代格式的響應式圖片 -->
<picture>
  <!-- 支援 AVIF 的瀏覽器使用(最佳壓縮) -->
  <source 
    srcset="
      /images/hero-400.avif 400w,
      /images/hero-800.avif 800w,
      /images/hero-1200.avif 1200w
    "
    type="image/avif"
    sizes="(max-width: 768px) 100vw, 50vw"
  >
  
  <!-- 支援 WebP 的瀏覽器使用 -->
  <source 
    srcset="
      /images/hero-400.webp 400w,
      /images/hero-800.webp 800w,
      /images/hero-1200.webp 1200w
    "
    type="image/webp"
    sizes="(max-width: 768px) 100vw, 50vw"
  >
  
  <!-- JPEG 備用 -->
  <img 
    src="/images/hero-800.jpg"
    srcset="
      /images/hero-400.jpg 400w,
      /images/hero-800.jpg 800w,
      /images/hero-1200.jpg 1200w
    "
    sizes="(max-width: 768px) 100vw, 50vw"
    alt="Hero image"
    width="1200"
    height="600"
    loading="lazy"
  >
</picture>
\`\`\`

#### 3. 延遲載入

\`\`\`html
<!-- 原生延遲載入 -->
<img 
  src="/image.jpg" 
  alt="Description"
  loading="lazy"
  width="800"
  height="600"
>

<!-- 首屏圖片使用立即載入 -->
<img 
  src="/hero.jpg" 
  alt="Hero"
  loading="eager"
  fetchpriority="high"
>
\`\`\`

#### 4. Next.js Image 元件

\`\`\`javascript
import Image from 'next/image';

// 自動最佳化
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority  // 用於首屏圖片
  quality={80}
/>

// 延遲載入
<Image
  src="/product.jpg"
  alt="Product"
  width={400}
  height={300}
  loading="lazy"
/>
\`\`\`

### 結果

| 指標 | 最佳化前 | 最佳化後 | 改善幅度 |
|--------|--------|-------|-------------|
| 總圖片大小 | 12MB | 1.8MB | 減少 85% |
| LCP | 4.5s | 1.6s | 加快 64% |
| 頁面載入(3G) | 18s | 4.2s | 加快 77% |

最佳實務

✅ 建議這樣做

  • 先測量 - 最佳化前務必建立基準指標
  • 使用 Lighthouse - 定期執行稽核以追蹤進度
  • 最佳化圖片 - 使用現代格式(WebP、AVIF)與響應式圖片
  • 程式碼分割 - 將大型打包拆成較小區塊
  • 延遲載入 - 延後非關鍵資源的載入
  • 積極快取 - 為靜態資源設定適當的快取標頭
  • 最小化主執行緒工作 - 將 JavaScript 執行時間控制在 50ms 區塊內
  • 預載關鍵資源 - 使用 <link rel="preload"> 預載關鍵資源
  • 使用 CDN - 從 CDN 提供靜態資源以加速傳遞
  • 監控真實使用者 - 追蹤真實使用者的 Core Web Vitals

❌ 避免這樣做

  • 不要盲目最佳化 - 先測量,再最佳化
  • 不要忽略行動裝置 - 在真實行動裝置與慢速網路上測試
  • 不要阻擋渲染 - 避免使用阻擋渲染的 CSS 與 JavaScript
  • 不要一次載入所有內容 - 延遲載入非關鍵資源
  • 不要忘記指定尺寸 - 務必指定圖片的寬度與高度
  • 不要使用同步腳本 - 使用 async 或 defer 屬性
  • 不要忽略第三方腳本 - 它們經常造成效能問題
  • 不要跳過壓縮 - 務必壓縮與最小化資源

常見陷阱

問題:針對桌面最佳化,但在行動裝置上緩慢

症狀: 桌面 Lighthouse 分數高,行動裝置分數低
解決方案:

  • 在真實行動裝置上測試
  • 使用 Chrome DevTools 行動裝置節流
  • 針對 3G/4G 網路最佳化
  • 減少 JavaScript 執行時間
# 使用節流測試
lighthouse https://yoursite.com --throttling.cpuSlowdownMultiplier=4

問題:大型 JavaScript 打包

症狀: 可互動時間(TTI)長,FID 高
解決方案:

  • 使用 webpack-bundle-analyzer 分析打包
  • 移除未使用的相依套件
  • 實作程式碼分割
  • 延遲載入非關鍵程式碼
# 分析打包
npx webpack-bundle-analyzer dist/stats.json

問題:圖片造成版面位移

症狀: CLS 分數高,內容跳動
解決方案:

  • 務必指定寬度與高度
  • 使用 aspect-ratio CSS 屬性
  • 使用骨架載入器保留空間
img {
  aspect-ratio: 16 / 9;
  width: 100%;
  height: auto;
}

問題:伺服器回應時間過慢

症狀: TTFB(第一個位元組時間)高
解決方案:

  • 實作伺服器端快取
  • 使用 CDN 提供靜態資源
  • 最佳化資料庫查詢
  • 考慮靜態網站產生(SSG)
// Next.js:靜態產生
export async function getStaticProps() {
  const data = await fetchData();
  return {
    props: { data },
    revalidate: 60 // 每 60 秒重新產生
  };
}

效能檢查清單

圖片

  • [ ] 轉換為現代格式(WebP、AVIF)
  • [ ] 實作響應式圖片
  • [ ] 加入延遲載入
  • [ ] 指定尺寸(寬度/高度)
  • [ ] 壓縮圖片(每張小於 200KB)
  • [ ] 使用 CDN 傳遞

JavaScript

  • [ ] 打包大小小於 200KB(gzip 後)
  • [ ] 實作程式碼分割
  • [ ] 延遲載入非關鍵程式碼
  • [ ] 移除未使用的相依套件
  • [ ] 最小化與壓縮
  • [ ] 對腳本使用 async/defer

CSS

  • [ ] 內嵌關鍵 CSS
  • [ ] 延遲非關鍵 CSS
  • [ ] 移除未使用的 CSS
  • [ ] 最小化 CSS 檔案
  • [ ] 使用 CSS containment

快取

  • [ ] 為靜態資源設定快取標頭
  • [ ] 實作 Service Worker
  • [ ] 使用 CDN 快取
  • [ ] 快取 API 回應
  • [ ] 對靜態資源進行版本管理

Core Web Vitals

  • [ ] LCP < 2.5s
  • [ ] FID < 100ms
  • [ ] CLS < 0.1
  • [ ] TTFB < 600ms
  • [ ] TTI < 3.8s

效能工具

測量工具

  • Lighthouse - 全面效能稽核
  • WebPageTest - 詳細瀑布圖分析
  • Chrome DevTools - 效能剖析
  • PageSpeed Insights - 真實使用者指標
  • Web Vitals Extension - 監控 Core Web Vitals

分析工具

  • webpack-bundle-analyzer - 視覺化打包組成
  • source-map-explorer - 分析打包大小
  • Bundlephobia - 安裝前檢查套件大小
  • ImageOptim - 圖片壓縮工具

監控工具

  • Google Analytics - 追蹤 Core Web Vitals
  • Sentry - 效能監控
  • New Relic - 應用程式效能監控
  • Datadog - 真實使用者監控

相關技能

  • @react-best-practices - React 效能模式
  • @frontend-dev-guidelines - 前端開發標準
  • @systematic-debugging - 除錯效能問題
  • @senior-architect - 效能架構

額外資源


專業提示: 優先專注於 Core Web Vitals(LCP、FID、CLS)——它們對使用者體驗與 SEO 排名影響最大!

限制

  • 僅在任務明確符合上述範圍時使用此技能。
  • 請勿將輸出視為環境特定驗證、測試或專家審查的替代方案。
  • 若缺少必要的輸入、權限、安全邊界或成功標準,請停止並要求釐清。