パフォーマンス最適化
Remixのパフォーマンス機能
プリフェッチング
prefetch="intent"でリンクホバー時にプリフェッチprefetch="render"で即座にプリフェッチ
// ✅ Good: ホバー時にプリフェッチ<Link prefetch="intent" to="/blog/post"> Post</Link>
// ✅ Good: 即座にプリフェッチ(重要なページ)<Link prefetch="render" to="/about"> About</Link>ローダーの最適化
- 必要なデータのみを取得
- 並列データフェッチを活用
// ✅ Good: 並列フェッチexport const loader = async ({ params }: LoaderFunctionArgs) => { const [post, comments, author] = await Promise.all([ getPost(params.slug), getComments(params.slug), getAuthor(params.slug), ]);
return json({ post, comments, author });};画像最適化
遅延読み込み
loading="lazy"で画像の遅延読み込み- ビューポート外の画像を最適化
// ✅ Good<img alt={title} loading="lazy" src={image} height="auto" width="auto"/>画像サイズの指定
widthとheightを明示的に指定- レイアウトシフトを防止
// ✅ Good<img alt="Description" height={400} loading="lazy" src="/image.jpg" width={800}/>React最適化
React.memo
- Propsが変更されない限り再レンダリングを防ぐ
- 大きなリストのアイテムに使用
// ✅ Goodexport const BlogPreview = React.memo(({ title, date }: BlogPreviewProps) => { return ( <div> <h3>{title}</h3> <p>{date}</p> </div> );});useMemo
- 計算コストが高い値をメモ化
- 依存配列を正確に指定
// ✅ Goodconst expensiveValue = useMemo(() => { return computeExpensiveValue(data);}, [data]);useCallback
- コールバック関数をメモ化
- 子コンポーネントの不要な再レンダリングを防止
// ✅ Goodconst handleClick = useCallback(() => { // ...}, [dependency]);コード分割
動的インポート
- 大きなライブラリは動的インポート
- 必要な時のみロード
// ✅ Good: 動的インポートconst HeavyComponent = lazy(() => import("./HeavyComponent"));
// 使用時<Suspense fallback={<Loading />}> <HeavyComponent /></Suspense>バンドルサイズの最適化
ツリーシェイキング
- 必要なモジュールのみをインポート
- 名前付きインポートを使用
// ✅ Good: 必要なもののみインポートimport { Link } from "@remix-run/react";
// ❌ Bad: 全体をインポートimport * as Remix from "@remix-run/react";外部ライブラリの最適化
- 軽量な代替ライブラリを検討
- 使用していない依存関係を削除
メタデータ最適化
メタ関数の最適化
- 必要なメタデータのみを返す
- 動的なメタデータを活用
// ✅ Goodexport const meta: MetaFunction<typeof loader> = ({ data }) => { return [ { title: data?.title || SITE_TITLE }, { name: "description", content: data?.description || SITE_DESCRIPTION }, ];};Lighthouse CI
パフォーマンス目標
- パフォーマンス: 90点以上
- アクセシビリティ: 90点以上
- ベストプラクティス: 90点以上
- SEO: 90点以上
# Lighthouse CI実行bun run lighthouseキャッシング
HTTPキャッシング
- 静的アセットに適切なキャッシュヘッダーを設定
- Cloudflare Pagesのキャッシング機能を活用
セッション管理
- Cookieベースのセッション管理
- 適切な有効期限を設定
const { getSession, commitSession } = createCookieSessionStorage({ cookie: { name: "__session", httpOnly: true, maxAge: 604_800, // 7日 path: "/", sameSite: "lax", secure: true, },});