Communitygithub.com

vite-patterns

Viteビルドツールのパターン集。設定、プラグイン、HMR、環境変数、プロキシ設定、SSR、ライブラリモード、依存関係の事前バンドル、ビルド最適化をカバー。vite.config.ts、Viteプラグイン、またはViteベースのプロジェクトで使用。

vite-patterns とは?

このスキルは、Vite 8+を使用する開発者向けに、設定、プラグイン、HMR(ホットモジュールリプレイスメント)、環境変数、プロキシ設定、ビルド最適化、ライブラリモード、SSR、依存関係の事前バンドル、および一般的な本番環境の落とし穴に関する包括的なパターンとベストプラクティスを提供します。開発モードではソースファイルをネイティブESMとして提供し、高速なコールドスタートと正確なHMRを実現し、ビルドモードではRolldown(v7以上)またはRollup(v5~v6)を使用してプロダクションバンドルを生成します。環境変数は静的にインライン化され、`VITE_`プレフィックス付きの変数のみがクライアントコードに公開されるため、セキュリティ上の注意点(例:`VITE_`プレフィックスはセキュリティ境界ではない)が強調されています。また、バレルファイルの回避、明示的なインポート拡張子の使用、ウォームアップルートによる開発サーバーのパフォーマンス最適化、`vite-plugin-checker`による型チェックの欠如への対処、`vite-plugin-dts`による型定義の生成など、具体的なユースケースに対応するプラグインの推奨やカスタムプラグイン作成のガイドラインも提供します。このスキルは、CLIツール(Claude Codeなど)、IDEエージェント(Cursorなど)、および一般的なAIコーディングエージェントで使用でき、Viteプロジェクトのトラブルシューティングや設定の最適化に役立ちます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/vite-patterns

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Vite パターン

Vite 8+ プロジェクト向けのビルドツールおよび開発サーバーのパターン集。設定、環境変数、プロキシ設定、ライブラリモード、依存関係の事前バンドル、および一般的な本番環境の落とし穴をカバーします。

使用タイミング

  • vite.config.ts または vite.config.js を設定する場合
  • 環境変数または .env ファイルを設定する場合
  • API バックエンド用の開発サーバープロキシを設定する場合
  • ビルド出力(チャンク、ミニファイ、アセット)を最適化する場合
  • build.lib を使用してライブラリを公開する場合
  • 依存関係の事前バンドルまたは CJS/ESM 相互運用に関するトラブルシューティングを行う場合
  • HMR、開発サーバー、またはビルドエラーをデバッグする場合
  • Vite プラグインの選択または順序付けを行う場合

仕組み

  • 開発モード では、ソースファイルをネイティブ ESM として提供します。バンドルは行われません。変換はモジュールリクエストごとにオンデマンドで実行されるため、コールドスタートが高速で HMR が正確です。
  • ビルドモード では、Rolldown(v7+)または Rollup(v5~v6)を使用して、ツリーシェイキング、コード分割、Oxc ベースのミニファイを備えたプロダクションバンドルを作成します。
  • 依存関係の事前バンドル は、CJS/UMD の依存関係を esbuild を使用して一度 ESM に変換し、結果を node_modules/.vite にキャッシュするため、以降の起動ではこの処理がスキップされます。
  • プラグイン は、開発とビルドで統一されたインターフェースを共有します。同じプラグインオブジェクトが、開発サーバーのオンデマンド変換とプロダクションパイプラインの両方で機能します。
  • 環境変数 は、ビルド時に静的にインライン化されます。VITE_ プレフィックスが付いた変数は、バンドル内で公開定数になります。プレフィックスがないものは、クライアントコードからは見えません。

例

設定構造

基本設定

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: { '@': new URL('./src', import.meta.url).pathname },
  },
})

条件付き設定

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd())   // VITE_ プレフィックスのみ(安全)

  return {
    plugins: [react()],
    server: command === 'serve' ? { port: 3000 } : undefined,
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

主要な設定オプション

キーデフォルト説明
root'.'プロジェクトルート(index.html がある場所)
base'/'デプロイされたアセットの公開ベースパス
envPrefix'VITE_'クライアント公開の環境変数のプレフィックス
build.outDir'dist'出力ディレクトリ
build.minify'oxc'ミニファイア('oxc'、'terser'、または false)
build.sourcemapfalsetrue、'inline'、または 'hidden'

プラグイン

必須プラグイン

ほとんどのプラグインニーズは、いくつかのメンテナンスが行き届いたパッケージでカバーされます。独自のプラグインを作成する前に、これらを試してください。

プラグイン目的使用タイミング
@vitejs/plugin-react-swcSWC による React HMR + Fast RefreshReact アプリのデフォルト(Babel 版より高速)
@vitejs/plugin-reactBabel による React HMR + Fast RefreshBabel プラグインが必要な場合のみ(emotion、MobX デコレータ)
@vitejs/plugin-vueVue 3 SFC サポートVue アプリ
vite-plugin-checkerワーカースレッドで tsc + ESLint を実行し、HMR オーバーレイを表示TypeScript アプリ全般 — Vite は vite build 時に型チェックを行いません
vite-tsconfig-pathstsconfig.json の paths エイリアスを尊重tsconfig.json にエイリアスが既にある場合
vite-plugin-dtsライブラリモードで .d.ts ファイルを生成TypeScript ライブラリを公開する場合
vite-plugin-svgrSVG を React コンポーネントとしてインポートSVG をコンポーネントとして使用する React アプリ
rollup-plugin-visualizerバンドルのツリーマップ/サンバーストレポート定期的なバンドルサイズ監査(enforce: 'post' を使用)
vite-plugin-pwaゼロ設定の PWA + Workboxオフライン対応アプリ

重要な注意: vite build はトランスパイルを行いますが、型チェックは行いません。vite-plugin-checker を追加するか、CI で tsc --noEmit を実行しない限り、型エラーはそのまま本番環境に出荷されます。

カスタムプラグインの作成

カスタムプラグインを作成することは稀です。ほとんどのニーズは既存のプラグインでカバーされます。必要な場合は、まず vite.config.ts にインラインで記述し、再利用する場合にのみ分離します。

// vite.config.ts — 最小限のインラインプラグイン
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',                       // 必須、一意である必要があります
    enforce: 'pre',                           // 'pre' | 'post'(オプション)
    apply: 'build',                           // 'build' | 'serve'(オプション)
    transform(code, id) {
      if (!id.endsWith('.custom')) return
      return { code: transformCustom(code), map: null }
    },
  }
}

主要なフック: transform(ソースの変更)、resolveId + load(仮想モジュール)、transformIndexHtml(HTML への注入)、configureServer(開発ミドルウェアの追加)、hotUpdate(カスタム HMR — v7+ で非推奨となった handleHotUpdate を置き換え)。

仮想モジュール は \0 プレフィックス規則を使用します。resolveId が '\0virtual:my-id' を返すため、他のプラグインはこれをスキップします。ユーザーコードは 'virtual:my-id' をインポートします。

完全なプラグイン API については、vite.dev/guide/api-plugin を参照してください。開発中は vite-plugin-inspect を使用して変換パイプラインをデバッグします。

HMR API

フレームワークプラグイン(@vitejs/plugin-react、@vitejs/plugin-vue など)は HMR を自動的に処理します。カスタム状態ストア、開発ツール、またはフレームワークに依存しないユーティリティを構築し、更新間で状態を維持する必要がある場合にのみ、import.meta.hot を直接使用してください。

// src/store.ts — バニラモジュールの手動 HMR
if (import.meta.hot) {
  // 更新間で状態を維持(.data を再代入せず、必ず MUTATE すること)
  import.meta.hot.data.count = import.meta.hot.data.count ?? 0

  // モジュールが置き換えられる前に副作用をクリーンアップ
  import.meta.hot.dispose((data) => clearInterval(data.intervalId))

  // このモジュール自身の更新を受け入れる
  import.meta.hot.accept()
}

すべての import.meta.hot コードはプロダクションビルドからツリーシェイキングされるため、ガードの削除は必要ありません。

環境変数

Vite は .env、.env.local、.env.[mode]、.env.[mode].local をこの順序で読み込みます(後で上書き)。*.local ファイルは gitignore され、ローカルシークレット用です。

クライアントサイドからのアクセス

VITE_ プレフィックスが付いた変数のみがクライアントコードに公開されます。

import.meta.env.VITE_API_URL   // 文字列
import.meta.env.MODE            // 'development' | 'production' | カスタム
import.meta.env.BASE_URL        // base 設定値
import.meta.env.DEV             // 真偽値
import.meta.env.PROD            // 真偽値
import.meta.env.SSR             // 真偽値

設定内で環境変数を使用する

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())          // VITE_ プレフィックスのみ(安全)
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

セキュリティ

VITE_ プレフィックスはセキュリティ境界ではありません

VITE_ プレフィックスが付いた変数はすべて、ビルド時に クライアントバンドルに静的にインライン化されます。ミニファイ、Base64 エンコード、ソースマップの無効化では隠せません。決意のある攻撃者は、出荷された JavaScript から任意の VITE_ 変数を抽出できます。

ルール: 公開値(API URL、機能フラグ、公開鍵)のみを VITE_ 変数に格納します。シークレット(API トークン、データベース URL、秘密鍵)は、API またはサーバーレス関数の背後でサーバーサイドに置く必要があります。

loadEnv('') の罠

// 悪い例: 第3引数に '' を渡すと、すべての環境変数(サーバーシークレットを含む)が読み込まれ、
// `define` を介してクライアントコードにインライン化できるようになります。
const env = loadEnv(mode, process.cwd(), '')

// 良い例: 明示的なプレフィックスリスト
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

本番環境のソースマップ

本番環境のソースマップは、元のソースコードを漏洩させます。エラートラッカー(Sentry、Bugsnag)にアップロードしてローカルで削除する場合を除き、無効にしてください。

build: {
  sourcemap: false,                                  // デフォルト — このまま維持
}

.gitignore チェックリスト

  • .env.local、.env.*.local — ローカルシークレットの上書き
  • dist/ — ビルド出力
  • node_modules/.vite — 事前バンドルキャッシュ(古いエントリが原因で誤ったエラーが発生する可能性があります)

サーバープロキシ

// vite.config.ts — server.proxy
server: {
  proxy: {
    '/foo': 'http://localhost:4567',                    // 文字列の短縮形

    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,                               // 仮想ホストバックエンドに必要
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
}

WebSocket プロキシの場合は、ルート設定に ws: true を追加します。

ビルド最適化

手動チャンク分割

// vite.config.ts — build.rolldownOptions
build: {
  rolldownOptions: {
    output: {
      // オブジェクト形式: 特定のパッケージをグループ化
      manualChunks: {
        'react-vendor': ['react', 'react-dom'],
        'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
      },
    },
  },
}
// 関数形式: ヒューリスティックで分割
manualChunks(id) {
  if (id.includes('node_modules/react')) return 'react-vendor'
  if (id.includes('node_modules')) return 'vendor'
}

パフォーマンス

バレルファイルを避ける

バレルファイル(index.ts がディレクトリ内のすべてを再エクスポートする)は、単一のシンボルをインポートする場合でも、Vite に再エクスポートされたすべてのファイルを強制的にロードさせます。これは、公式ドキュメントで指摘されている開発サーバー速度低下の最大の原因です。

// 悪い例 — 1つのユーティリティをインポートするだけで、バレル全体をロードする
import { slash } from '@/utils'

// 良い例 — 直接インポート、1つのファイルのみがロードされる
import { slash } from '@/utils/slash'

インポート拡張子を明示する

暗黙の拡張子ごとに、resolve.extensions を介して最大6回のファイルシステムチェックが強制されます。大規模なコードベースでは、これが積み重なります。

// 悪い例
import Component from './Component'

// 良い例
import Component from './Component.tsx'

tsconfig.json の allowImportingTsExtensions と resolve.extensions を、実際に使用する拡張子のみに絞り込みます。

ホットパスルートをウォームアップする

server.warmup.clientFiles は、ブラウザがリクエストする前に、既知のホットエントリを事前変換します。これにより、大規模アプリでのコールドロードのリクエストウォーターフォールが解消されます。

// vite.config.ts
server: {
  warmup: {
    clientFiles: ['./src/main.tsx', './src/routes/**/*.tsx'],
  },
}

遅い開発サーバーのプロファイリング

vite dev が遅いと感じたら、vite --profile で開始し、アプリを操作してから p+enter を押して .cpuprofile を保存します。Speedscope にロードして、どのプラグインが時間を消費しているか(通常はコミュニティプラグインの buildStart、config、または configResolved フック)を特定します。

ライブラリモード

npm パッケージを公開する場合は、build.lib を使用します。設定の詳細よりも、2つの落とし穴が重要です。

  1. 型は出力されません — vite-plugin-dts を追加するか、tsc --emitDeclarationOnly を個別に実行します。
  2. ピア依存関係は必ず外部化する必要があります — リストにないピアはライブラリにバンドルされ、コンシューマーで重複ランタイムエラーが発生します。
// vite.config.ts
build: {
  lib: {
    entry: 'src/index.ts',
    formats: ['es', 'cjs'],
    fileName: (format) => `my-lib.${format}.js`,
  },
  rolldownOptions: {
    external: ['react', 'react-dom', 'react/jsx-runtime'],  // すべてのピア依存関係
  },
}

SSR 外部化

ベアの createServer({ middlewareMode: true }) セットアップは、フレームワーク作成者の領域です。ほとんどのアプリでは、代わりに Nuxt、Remix、SvelteKit、Astro、または TanStack Start を使用する必要があります。フレームワークユーザーとして調整するのは、依存関係が SSR で壊れた場合の外部化設定です。

// vite.config.ts — ssr オプション
ssr: {
  external: ['node-native-package'],           // SSR バンドルでは require() として保持
  noExternal: ['esm-only-package'],            // SSR 出力に強制バンドル(ほとんどの SSR エラーを修正)
  target: 'node',                              // 'node' または 'webworker'
}

依存関係の事前バンドル

Vite は依存関係を事前バンドルして、CJS/UMD を ESM に変換し、リクエスト数を削減します。

// vite.config.ts — optimizeDeps
optimizeDeps: {
  include: [
    'lodash-es',                              // 既知の重い依存関係を強制的に事前バンドル
    'cjs-package',                            // 相互運用の問題を引き起こす CJS 依存関係
    'deep-lib/components/**',                 // 深いインポートのグロブ
  ],
  exclude: ['local-esm-package'],             // 除外する場合は有効な ESM である必要があります
  force: true,                                // キャッシュを無視して再最適化(一時的なデバッグ用)
}

よくある落とし穴

開発環境とビルド環境の不一致

開発環境では esbuild/Rolldown が変換に使用され、ビルド環境では Rolldown がバンドルに使用されます。CJS ライブラリは、2つの間で動作が異なる場合があります。デプロイ前に必ず vite build && vite preview で確認してください。

デプロイ後の古いチャンク

新しいビルドは新しいチャンクハッシュを生成します。アクティブなセッションを持つユーザーは、もう存在しない古いファイル名をリクエストします。Vite には組み込みの解決策はありません。軽減策:

  • デプロイウィンドウの間、古い dist/assets/ ファイルを存続させる
  • ルーターで動的インポートエラーをキャッチし、ページを強制リロードする

Docker とコンテナ

Vite はデフォルトで localhost にバインドするため、コンテナの外部からは到達できません。

// vite.config.ts — Docker/コンテナ設定
server: {
  host: true,                                  // 0.0.0.0 にバインド
  hmr: { clientPort: 3000 },                   // リバースプロキシの背後にある場合
}

モノレポのファイルアクセス

Vite はファイルの提供をプロジェクトルートに制限します。ルート外のパッケージはブロックされます。

// vite.config.ts — モノレポファイルアクセス
server: {
  fs: {
    allow: ['..'],                             // 親ディレクトリ(ワークスペースルート)を許可
  },
}

アンチパターン

// 悪い例: envPrefix を '' に設定すると、すべての環境変数(シークレットを含む)がクライアントに公開される
envPrefix: ''

// 悪い例: Vite のブラウザコードで require() が機能すると仮定する

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

関連スキル