frontend-performance について
Next.js 開発者向けのフロントエンド性能最適化スキルです。プロダクション環境の監査やバンドル分析に加え、インポート、アニメーション、サーバー処理、画像の改善方法を扱います。
主な機能
- 01プロダクション環境の Lighthouse 監査
- 02バンドル分析とボトルネック調査
- 03インポートとアニメーションの最適化
- 04計算処理のサーバー移行
- 05Next.js の画像最適化
活用シーン
- 01性能の基準値を測定して再検証
- 02バンドルを肥大化させる依存関係の特定
- 03アニメーションとクライアント計算の負荷軽減
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ b-open-io/ prompts --skill frontend-performanceインストール後、Claude Code で/frontend-performanceを入力して読み込まれたか確認します。
同梱ファイル.clawnet/unsigned-skill.json
詳細
フロントエンドのパフォーマンス最適化
Next.js アプリケーションのパフォーマンス問題を診断し、修正します。
クイック診断
Lighthouse CLI を実行する
# Performance audit (headless)
npx lighthouse http://localhost:3000 --output=json --output-path=./lighthouse.json --chrome-flags="--headless" --only-categories=performance
# Parse key metrics
cat lighthouse.json | jq '{
score: .categories.performance.score,
FCP: .audits["first-contentful-paint"].displayValue,
LCP: .audits["largest-contentful-paint"].displayValue,
TBT: .audits["total-blocking-time"].displayValue,
CLS: .audits["cumulative-layout-shift"].displayValue
}'
# Find slow scripts
cat lighthouse.json | jq '.audits["bootup-time"].details.items | .[0:8]'
# Main thread breakdown
cat lighthouse.json | jq '.audits["mainthread-work-breakdown"].details.items'
重要:必ず本番ビルド(next build && next start)をテストしてください。開発モードでは、HMR、ソースマップ、最適化が行われないことにより、オーバーヘッドが 2~10 倍になります。
バンドルの分析
# Install
bun add -d @next/bundle-analyzer
# Run analysis
ANALYZE=true bun run build
next.config.js で設定します:
import bundleAnalyzer from '@next/bundle-analyzer'
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
})
export default withBundleAnalyzer(nextConfig)
よくある修正方法
1. optimizePackageImports
エクスポート数の多いライブラリ(アイコン、ユーティリティ、アニメーションライブラリなど)向け:
// next.config.js
const nextConfig = {
experimental: {
optimizePackageImports: [
'framer-motion',
'lucide-react',
'@phosphor-icons/react',
'lodash',
'date-fns',
'@heroicons/react',
],
},
}
これにより、ツリーシェイキングが正しく機能し、使用するインポートのみがバンドルされます。
2. Framer Motion — Variants パターン
誤り — N 個のアニメーションコントローラーが作成されます:
// Each element has its own animation state - expensive!
{items.map((item, i) => (
<motion.div
key={i}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: i * 0.05 }} // Individual delays
>
{item}
</motion.div>
))}
正しい — staggerChildren を使った単一のコントローラー:
// Parent controls all children - efficient!
const containerVariants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.05,
},
},
}
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: { type: 'spring' as const, damping: 15 }
},
}
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
>
{items.map((item, i) => (
<motion.div key={i} variants={itemVariants}>
{item}
</motion.div>
))}
</motion.div>
次の点にも注意してください:
- アニメーションでの
filter: blur()— 非常に負荷が高くなります - 無限アニメーションの使いすぎ(数を減らすか、CSS を使用してください)
- variants を使用する場合の、子要素への個別の
transitionprops
3. 重い計算をサーバーサイドに移す
次の処理をクライアントバンドルに含めないでください:
- シンタックスハイライト:
prism-react-rendererではなく、サーバーサイドでshikiを使用します - Markdown の解析:サーバーでレンダリングします
- 日付フォーマットライブラリ:
Intl.DateTimeFormatの使用を検討します - 大規模なデータ変換:API ルートまたはサーバーコンポーネントを使用します
4. 画像の最適化
// Always use next/image
import Image from 'next/image'
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // For LCP images
placeholder="blur" // Reduces CLS
/>
5. フォントの最適化
// app/layout.tsx
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap', // Prevents FOIT
preload: true,
})
6. 外部パッケージ(サーバーのみ)
サーバー専用パッケージがバンドルされないようにします:
// next.config.js
const nextConfig = {
serverExternalPackages: ['sharp', 'canvas'],
}
パフォーマンス目標
| 指標 | 良好 | 要改善 | 不良 |
|---|---|---|---|
| LCP | ≤2.5s | 2.5-4s | >4s |
| FCP | ≤1.8s | 1.8-3s | >3s |
| TBT | ≤200ms | 200-600ms | >600ms |
| CLS | ≤0.1 | 0.1-0.25 | >0.25 |
デバッグのワークフロー
- 本番環境で Lighthouse を実行する — ベースラインの指標を取得します
- bootup-time 監査を確認する — 遅いスクリプトを特定します
- バンドルアナライザーを実行する — 大きなチャンクを特定します
- 最大の問題から修正する — 通常、1~2 個のパッケージが問題の大半を引き起こしています
- 再テストする — 改善を確認します
すぐにできる改善のチェックリスト
- 開発環境ではなく、本番ビルドをテストする
- アイコン/ユーティリティライブラリに
optimizePackageImportsを追加する - Framer Motion の variants パターンを使用する
- アニメーションから
filter: blur()を削除する - LCP 画像に
priorityを追加する -
display: swapを指定してnext/fontを使用する - 重いライブラリをサーバーコンポーネントに移す
コメント
Markdown 対応