performance-optimization について
Webアプリケーションを最適化する開発者向けのフロントエンド性能リファレンスです。バンドル分析、コード分割、画像最適化、Core Web Vitalsの監視と実装項目をまとめています。
主な機能
- 01バンドル分析とコード分割
- 02画像最適化の実践
- 03Core Web Vitalsの監視
- 04キャッシュとアセット配信の確認
- 05性能アンチパターンのチェックリスト
活用シーン
- 01初期JavaScript読み込み量の削減
- 02画像配信とレイアウト安定性の改善
- 03LCP、INP、CLSの監視
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ rohitg00/ awesome-claude-code-toolkit --skill performance-optimizationインストール後、Claude Code で/performance-optimizationを入力して読み込まれたか確認します。
詳細
パフォーマンスの最適化
バンドル分析とコード分割
// Dynamic import for route-level code splitting
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Settings = lazy(() => import("./pages/Settings"));
function App() {
return (
<Suspense fallback={<PageSkeleton />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
// vite.config.ts - manual chunk splitting
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
charts: ["recharts", "d3"],
editor: ["@monaco-editor/react"],
},
},
},
},
});
# Analyze bundle composition
npx vite-bundle-visualizer
npx source-map-explorer dist/assets/*.js
画像の最適化
import Image from "next/image";
function ProductImage({ src, alt }: { src: string; alt: string }) {
return (
<Image
src={src}
alt={alt}
width={800}
height={600}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
placeholder="blur"
blurDataURL={generateBlurHash(src)}
loading="lazy"
/>
);
}
<img
src="product.webp"
alt="Product photo"
width="800"
height="600"
loading="lazy"
decoding="async"
fetchpriority="low"
/>
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />
キャッシュヘッダー
function setCacheHeaders(res: Response, options: CacheOptions) {
if (options.immutable) {
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
return;
}
if (options.revalidate) {
res.setHeader("Cache-Control", `public, max-age=0, s-maxage=${options.revalidate}, stale-while-revalidate=${options.staleWhileRevalidate ?? 86400}`);
return;
}
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
}
app.use("/assets", (req, res, next) => {
setCacheHeaders(res, { immutable: true });
next();
});
app.use("/api", (req, res, next) => {
setCacheHeaders(res, { revalidate: 60, staleWhileRevalidate: 3600 });
next();
});
大量データ向けの仮想リスト
import { useVirtualizer } from "@tanstack/react-virtual";
function VirtualList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
overscan: 5,
});
return (
<div ref={parentRef} style={{ height: "600px", overflow: "auto" }}>
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: "relative" }}>
{virtualizer.getVirtualItems().map((virtualRow) => (
<div
key={virtualRow.key}
style={{
position: "absolute",
top: 0,
transform: `translateY(${virtualRow.start}px)`,
height: `${virtualRow.size}px`,
width: "100%",
}}
>
<ItemRow item={items[virtualRow.index]} />
</div>
))}
</div>
</div>
);
}
Core Web Vitals のモニタリング
import { onCLS, onINP, onLCP } from "web-vitals";
function sendMetric(metric: { name: string; value: number; id: string }) {
navigator.sendBeacon("/api/vitals", JSON.stringify(metric));
}
onCLS(sendMetric);
onINP(sendMetric);
onLCP(sendMetric);
- LCP(Largest Contentful Paint):2.5秒未満。ヒーロー画像を事前読み込みし、サーバーの応答時間を最適化します。
- INP(Interaction to Next Paint):200ミリ秒未満。長時間のタスクを避け、
requestIdleCallbackを使用します。 - CLS(Cumulative Layout Shift):0.1未満。画像と埋め込みコンテンツには明示的なサイズを設定します。
アンチパターン
- ルートごとにコード分割せず、すべての JavaScript を最初に読み込む
- 最適化されていない画像を配信する(WebP/AVIF を使用せず、レスポンシブサイズも指定しない)
- 画像に
widthとheightを指定しない(レイアウトシフトの原因になります) - コンテンツハッシュ付きの静的アセットに
Cache-Control: no-cacheを使用する - リストを仮想化せず、数千の DOM ノードをレンダリングする
- 同期的な計算でメインスレッドをブロックする
チェックリスト
- ルートを
import()と Suspense で遅延読み込みする - バンドルを分析し、ベンダーチャンクを分離する
- レスポンシブな
sizes属性を指定し、画像を WebP/AVIF 形式で配信する - LCP 画像を
fetchpriority="high"で事前読み込みする - 静的アセットを、イミュータブルヘッダーとコンテンツハッシュを使用してキャッシュする
- 100 件以上のアイテムを含むリストを仮想化する
- 本番環境で Core Web Vitals(LCP、INP、CLS)をモニタリングする
- クリティカルパスにレンダリングをブロックするリソースがない
コメント
Markdown 対応