mcpField
W
web-performance-optimization

web-performance-optimization

github.com/secondsky開発240567 回インストール5 週間前に更新
リポジトリ

web-performance-optimization について

Web 開発者向けのパフォーマンス最適化スキルです。読み込み、キャッシュ、圧縮、監視の手法を扱い、Core Web Vitals とユーザー体験の改善に役立ちます。

主な機能

  1. 01ルートのコード分割と遅延読み込み
  2. 02画像の最適化とキャッシュ
  3. 03gzip と Brotli による圧縮
  4. 04Core Web Vitals の監視
  5. 05パフォーマンス指標の目標

活用シーン

  1. 01ページ読み込みの遅さの調査
  2. 02大きなフロントエンドバンドルの縮小
  3. 03モバイル性能の改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill web-performance-optimization

インストール後、Claude Code で/web-performance-optimizationを入力して読み込まれたか確認します。

同梱ファイルreferences/compression-monitoring.mdreferences/typescript-advanced.md

詳細

Web パフォーマンス最適化

概要

遅延読み込み、コード分割、キャッシュ、圧縮、モニタリングなどのパフォーマンス最適化戦略を実装して、Core Web Vitals とユーザーエクスペリエンスを改善します。

使用する場面

  • ページの読み込みに時間がかかる
  • Largest Contentful Paint(LCP)の値が高い
  • バンドルサイズが大きい
  • Cumulative Layout Shift(CLS)が頻繁に発生する
  • モバイルでパフォーマンスの問題がある

コード分割(React)

import { lazy, Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

Webpack バンドルの最適化

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
};

画像の最適化

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img
    src="image.jpg"
    srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, 50vw"
    loading="lazy"
    decoding="async"
    alt="Description"
  >
</picture>

Service Worker キャッシュ

// sw.js
const CACHE_NAME = 'app-v1';
const ASSETS = ['/', '/index.html', '/main.js', '/styles.css'];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      return cached || fetch(event.request).then(response => {
        return caches.open(CACHE_NAME).then(cache => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

Core Web Vitals のモニタリング

// Track LCP, CLS, INP (Note: INP replaced FID as of March 2024)
// sendToAnalytics is a placeholder function that sends metrics to your analytics endpoint
// Expected signature: sendToAnalytics({ metric: string, value: number }) => void
// Example implementation:
function sendToAnalytics({ metric, value }) {
  // Replace with your analytics implementation (e.g., Google Analytics, Segment)
  fetch('/api/analytics', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ metric, value, timestamp: Date.now() })
  });
}

// Largest Contentful Paint (LCP)
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`LCP: ${entry.startTime}ms`);
    sendToAnalytics({ metric: 'LCP', value: entry.startTime });
  }
}).observe({ type: 'largest-contentful-paint', buffered: true });

// Cumulative Layout Shift (CLS)
new PerformanceObserver((list) => {
  let cls = 0;
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) cls += entry.value;
  }
  sendToAnalytics({ metric: 'CLS', value: cls });
}).observe({ type: 'layout-shift', buffered: true });

// Interaction to Next Paint (INP) - replaces FID
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // INP measures responsiveness - duration of slowest interaction
    const inp = entry.processingEnd - entry.processingStart;
    console.log(`INP: ${inp}ms`);
    sendToAnalytics({ metric: 'INP', value: inp });
  }
}).observe({ type: 'event', buffered: true }); // 'event' captures interaction events

パフォーマンス目標

指標良好改善が必要
LCP<2.5s2.5-4s
INP<200ms200-500ms
CLS<0.10.1-0.25
TTI<3.8s3.8-7.3s

注: INP(Interaction to Next Paint)は、2024年3月にCore Web VitalとしてFID(First Input Delay)に置き換わりました。INPは、入力遅延だけでなく操作にかかる時間全体を測定するため、ページの応答性をより包括的に評価できます。

圧縮(Nginx)

gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
gzip_comp_level 6;

ベストプラクティス

  • コード分割でバンドルサイズを最小限に抑える
  • 適切な形式を使用して画像を最適化する
  • 戦略的に遅延読み込みを実装する
  • HTTP キャッシュヘッダーを使用する
  • gzip/brotli 圧縮を有効にする
  • Core Web Vitals を継続的にモニタリングする
  • service worker を実装する
  • 重要度の低い JavaScript の読み込みを遅らせる
  • クリティカルレンダリングパスを最適化する
  • 実際のデバイスとネットワークでテストする

最適化チェックリスト

  • ルートごとにコード分割を有効にする
  • ファーストビューより下のコンポーネントを遅延読み込みする
  • 画像を最適化して圧縮する
  • service worker によるキャッシュを実装する
  • gzip/brotli 圧縮を有効にする
  • Core Web Vitals をモニタリングする
  • レンダリングをブロックするリソースを最小限に抑える

追加設定

以下については、references/compression-monitoring.md を参照してください。

  • Webpack 圧縮プラグインのセットアップ
  • Apache .htaccess 圧縮設定
  • TTFB モニタリングの実装
  • 測定のための Puppeteer 自動化

以下については、references/typescript-advanced.md を参照してください。

  • TypeScript の lazyLoad ユーティリティ
  • TypeScript の画像コンポーネント
  • オフライン時のフォールバックに対応した高度な service worker
  • TerserPlugin の設定
  • PerformanceMetrics インターフェースの全体

ツール

  • Lighthouse / PageSpeed Insights
  • WebPageTest
  • Chrome DevTools の Performance タブ
  • web-vitals npm パッケージ

リソース

コメント