web-performance-optimization について
開発者向けのウェブ性能最適化スキルです。計測、問題の特定、改善、検証を通じて、読み込み速度や実行時性能、Core Web Vitals の改善を支援します。
主な機能
- 01性能の基準値を計測
- 02性能ボトルネックの分析
- 03アセットと描画経路の最適化
- 04キャッシュと遅延読み込みの適用
- 05改善結果の検証
活用シーン
- 01読み込みが遅いサイトの調査
- 02Core Web Vitals の改善
- 03JavaScript バンドルの縮小
- 04性能監査の準備
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill web-performance-optimizationインストール後、Claude Code で/web-performance-optimizationを入力して読み込まれたか確認します。
詳細
Web パフォーマンス最適化
概要
開発者がウェブサイトおよびウェブアプリケーションのパフォーマンスを最適化し、ユーザーエクスペリエンス、SEO ランキング、コンバージョン率を向上できるよう支援します。このスキルは、読み込み速度、ランタイムパフォーマンス、Core Web Vitals 指標を計測、分析、改善するための体系的なアプローチを提供します。
このスキルを使用するタイミング
- ウェブサイトやアプリの読み込みが遅いとき
- Core Web Vitals (LCP、FID、CLS) を最適化するとき
- JavaScript バンドルサイズを削減するとき
- Time to Interactive (TTI) を改善するとき
- 画像とアセットを最適化するとき
- キャッシュ戦略を実装するとき
- パフォーマンスのボトルネックをデバッグするとき
- パフォーマンス監査に備えるとき
仕組み
ステップ 1: 現在のパフォーマンスを計測する
ベースライン指標の把握をお手伝いします:
- Lighthouse 監査を実行する
- Core Web Vitals (LCP、FID、CLS) を計測する
- バンドルサイズを確認する
- ネットワークウォーターフォールを分析する
- パフォーマンスのボトルネックを特定する
ステップ 2: 問題を特定する
パフォーマンスの問題を分析します:
- 大きな JavaScript バンドル
- 最適化されていない画像
- レンダリングをブロックするリソース
- サーバー応答時間の遅さ
- キャッシュヘッダーの欠如
- レイアウトシフト
- メインスレッドをブロックする長いタスク
ステップ 3: 最適化の優先順位を決める
効果の大きい改善に注力します:
- クリティカルレンダリングパスの最適化
- コード分割と遅延読み込み
- 画像の最適化
- キャッシュ戦略
- サードパーティスクリプトの最適化
ステップ 4: 最適化を実装する
パフォーマンス改善を適用します:
- アセット (画像、フォント、CSS、JS) を最適化する
- コード分割を実装する
- キャッシュヘッダーを追加する
- 重要度の低いリソースを遅延読み込みする
- クリティカルレンダリングパスを最適化する
ステップ 5: 改善を検証する
変更の効果を計測します:
- Lighthouse 監査を再実行する
- 改善前後の指標を比較する
- リアルユーザー指標 (RUM) を監視する
- さまざまなデバイスやネットワークでテストする
例
例 1: Core Web Vitals の最適化
## Performance Audit Results
### Current Metrics (Before Optimization)
- **LCP (Largest Contentful Paint):** 4.2s ❌ (should be < 2.5s)
- **FID (First Input Delay):** 180ms ❌ (should be < 100ms)
- **CLS (Cumulative Layout Shift):** 0.25 ❌ (should be < 0.1)
- **Lighthouse Score:** 62/100
### Issues Identified
1. **LCP Issue:** Hero image (2.5MB) loads slowly
2. **FID Issue:** Large JavaScript bundle (850KB) blocks main thread
3. **CLS Issue:** Images without dimensions cause layout shifts
### Optimization Plan
#### Fix LCP (Largest Contentful Paint)
**Problem:** Hero image is 2.5MB and loads slowly
**Solutions:**
\`\`\`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>
\`\`\`
**Additional optimizations:**
- Compress image to < 200KB
- Use CDN for faster delivery
- Preload hero image: `<link rel="preload" as="image" href="/hero.avif">`
#### Fix FID (First Input Delay)
**Problem:** 850KB JavaScript bundle blocks main thread
**Solutions:**
1. **Code Splitting:**
\`\`\`javascript
// Before: Everything in one bundle
import { HeavyComponent } from './HeavyComponent';
import { Analytics } from './analytics';
import { ChatWidget } from './chat';
// After: Lazy load non-critical code
const HeavyComponent = lazy(() => import('./HeavyComponent'));
const ChatWidget = lazy(() => import('./chat'));
// Load analytics after page interactive
if (typeof window !== 'undefined') {
window.addEventListener('load', () => {
import('./analytics').then(({ Analytics }) => {
Analytics.init();
});
});
}
\`\`\`
2. **Remove Unused Dependencies:**
\`\`\`bash
# Analyze bundle
npx webpack-bundle-analyzer
# Remove unused packages
npm uninstall moment # Use date-fns instead (smaller)
npm install date-fns
\`\`\`
3. **Defer Non-Critical Scripts:**
\`\`\`html
<script src="/analytics.js"></script>
<script src="/analytics.js" defer></script>
\`\`\`
#### Fix CLS (Cumulative Layout Shift)
**Problem:** Images without dimensions cause layout shifts
**Solutions:**
\`\`\`html
<img src="/product.jpg" alt="Product">
<img
src="/product.jpg"
alt="Product"
width="400"
height="300"
style="aspect-ratio: 4/3;"
>
\`\`\`
**For dynamic content:**
\`\`\`css
/* Reserve space for content that loads later */
.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; }
}
\`\`\`
### Results After Optimization
- **LCP:** 1.8s ✅ (improved by 57%)
- **FID:** 45ms ✅ (improved by 75%)
- **CLS:** 0.05 ✅ (improved by 80%)
- **Lighthouse Score:** 94/100 ✅
例 2: JavaScript バンドルサイズの削減
## Bundle Size Optimization
### Current State
- **Total Bundle:** 850KB (gzipped: 280KB)
- **Main Bundle:** 650KB
- **Vendor Bundle:** 200KB
- **Load Time (3G):** 8.2s
### Analysis
\`\`\`bash
# Analyze bundle composition
npx webpack-bundle-analyzer dist/stats.json
\`\`\`
**Findings:**
1. Moment.js: 67KB (can replace with date-fns: 12KB)
2. Lodash: 72KB (using entire library, only need 5 functions)
3. Unused code: ~150KB of dead code
4. No code splitting: Everything in one bundle
### Optimization Steps
#### 1. Replace Heavy Dependencies
\`\`\`bash
# Remove moment.js (67KB) → Use date-fns (12KB)
npm uninstall moment
npm install date-fns
# Before
import moment from 'moment';
const formatted = moment(date).format('YYYY-MM-DD');
# After
import { format } from 'date-fns';
const formatted = format(date, 'yyyy-MM-dd');
\`\`\`
**Savings:** 55KB
#### 2. Use Lodash Selectively
\`\`\`javascript
// Before: Import entire library (72KB)
import _ from 'lodash';
const unique = _.uniq(array);
// After: Import only what you need (5KB)
import uniq from 'lodash/uniq';
const unique = uniq(array);
// Or use native methods
const unique = [...new Set(array)];
\`\`\`
**Savings:** 67KB
#### 3. Implement Code Splitting
\`\`\`javascript
// Next.js example
import dynamic from 'next/dynamic';
// Lazy load heavy components
const Chart = dynamic(() => import('./Chart'), {
loading: () => <div>Loading chart...</div>,
ssr: false
});
const AdminPanel = dynamic(() => import('./AdminPanel'), {
loading: () => <div>Loading...</div>
});
// Route-based code splitting (automatic in Next.js)
// pages/admin.js - Only loaded when visiting /admin
// pages/dashboard.js - Only loaded when visiting /dashboard
\`\`\`
#### 4. Remove Dead Code
\`\`\`javascript
// Enable tree shaking in webpack.config.js
module.exports = {
mode: 'production',
optimization: {
usedExports: true,
sideEffects: false
}
};
// In package.json
{
"sideEffects": false
}
\`\`\`
#### 5. Optimize Third-Party Scripts
\`\`\`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>
\`\`\`
### Results
- **Total Bundle:** 380KB ✅ (reduced by 55%)
- **Main Bundle:** 180KB ✅
- **Vendor Bundle:** 80KB ✅
- **Load Time (3G):** 3.1s ✅ (improved by 62%)
例 3: 画像最適化の戦略
## Image Optimization
### Current Issues
- 15 images totaling 12MB
- No modern formats (WebP, AVIF)
- No responsive images
- No lazy loading
### Optimization Strategy
#### 1. Convert to Modern Formats
\`\`\`bash
# Install image optimization tools
npm install sharp
# Conversion script (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));
// Generate WebP
await sharp(inputPath)
.webp({ quality: 80 })
.toFile(path.join(outputDir, \`\${filename}.webp\`));
// Generate AVIF (best compression)
await sharp(inputPath)
.avif({ quality: 70 })
.toFile(path.join(outputDir, \`\${filename}.avif\`));
// Generate optimized JPEG fallback
await sharp(inputPath)
.jpeg({ quality: 80, progressive: true })
.toFile(path.join(outputDir, \`\${filename}.jpg\`));
}
// Process all images
const images = fs.readdirSync('./images');
images.forEach(img => {
optimizeImage(\`./images/\${img}\`, './images/optimized');
});
\`\`\`
#### 2. Implement Responsive Images
\`\`\`html
<picture>
<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"
>
<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"
>
<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. Lazy Loading
\`\`\`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 Component
\`\`\`javascript
import Image from 'next/image';
// Automatic optimization
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // For above-the-fold images
quality={80}
/>
// Lazy loaded
<Image
src="/product.jpg"
alt="Product"
width={400}
height={300}
loading="lazy"
/>
\`\`\`
### Results
| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| Total Image Size | 12MB | 1.8MB | 85% reduction |
| LCP | 4.5s | 1.6s | 64% faster |
| Page Load (3G) | 18s | 4.2s | 77% faster |
ベストプラクティス
✅ 推奨事項
- まず計測する - 最適化の前に必ずベースライン指標を確立する
- Lighthouse を使う - 進捗を追跡するために定期的に監査を実行する
- 画像を最適化する - 最新のフォーマット (WebP、AVIF) とレスポンシブ画像を使用する
- コードを分割する - 大きなバンドルを小さなチャンクに分割する
- 遅延読み込みする - 重要度の低いリソースの読み込みを遅らせる
- 積極的にキャッシュする - 静的アセットに適切なキャッシュヘッダーを設定する
- メインスレッドの作業を最小化する - JavaScript の実行を 50ms 以下のチャンクに保つ
- 重要なリソースをプリロードする - 重要なアセットには
<link rel="preload">を使用する - CDN を使用する - 静的アセットを CDN から配信して高速化する
- 実際のユーザーを監視する - 実ユーザーから Core Web Vitals を収集する
❌ 避けるべきこと
- やみくもに最適化しない - まず計測し、その後で最適化する
- モバイルを無視しない - 実際のモバイル端末や低速ネットワークでテストする
- レンダリングをブロックしない - レンダリングをブロックする CSS と JavaScript を避ける
- すべてを最初に読み込まない - 重要度の低いリソースは遅延読み込みする
- 寸法を指定し忘れない - 画像には必ず幅と高さを指定する
- 同期スクリプトを使用しない - async または defer 属性を使用する
- サードパーティスクリプトを無視しない - パフォーマンス問題の原因になることが多い
- 圧縮を省略しない - アセットは必ず圧縮および minify する
よくある落とし穴
問題: デスクトップ向けには最適化されているが、モバイルで遅い
症状: デスクトップでは Lighthouse スコアが良いが、モバイルでは悪い 解決策:
- 実際のモバイル端末でテストする
- Chrome DevTools のモバイルスロットリングを使用する
- 3G/4G ネットワーク向けに最適化する
- JavaScript の実行時間を短縮する
# Test with throttling
lighthouse https://yoursite.com --throttling.cpuSlowdownMultiplier=4
問題: JavaScript バンドルが大きい
症状: Time to Interactive (TTI) が長い、FID が高い 解決策:
- webpack-bundle-analyzer でバンドルを分析する
- 未使用の依存関係を削除する
- コード分割を実装する
- 重要度の低いコードを遅延読み込みする
# Analyze bundle
npx webpack-bundle-analyzer dist/stats.json
問題: レイアウトシフトを引き起こす画像
症状: CLS スコアが高い、コンテンツが跳ねる 解決策:
- 常に幅と高さを指定する
- aspect-ratio CSS プロパティを使用する
- スケルトンローダーで領域を確保する
img {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
問題: サーバー応答時間が遅い
症状: TTFB (Time to First Byte) が高い 解決策:
- サーバーサイドキャッシュを実装する
- 静的アセットに CDN を使用する
- データベースクエリを最適化する
- 静的サイト生成 (SSG) を検討する
// Next.js: Static generation
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
revalidate: 60 // Regenerate every 60 seconds
};
}
パフォーマンスチェックリスト
画像
- 最新フォーマット (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.5 秒
- FID < 100 ミリ秒
- CLS < 0.1
- TTFB < 600 ミリ秒
- TTI < 3.8 秒
パフォーマンスツール
計測ツール
- 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- パフォーマンスのためのアーキテクチャ
追加リソース
- Web.dev Performance
- Core Web Vitals
- Lighthouse Documentation
- MDN Performance Guide
- Next.js Performance
- Image Optimization Guide
Pro Tip: まずは Core Web Vitals (LCP、FID、CLS) に注力しましょう。ユーザー体験と SEO のランキングに最も大きな影響を与えます。
コメント
Markdown 対応