T-CREATOR

【保存版】Vite 設定オプション早見表:`resolve` / `optimizeDeps` / `build` / `server`

【保存版】Vite 設定オプション早見表:`resolve` / `optimizeDeps` / `build` / `server`

Vite は近年多くの開発者に愛用されているビルドツールです。しかし、その豊富な設定オプションの中でも特に重要な resolveoptimizeDepsbuildserver の各オプションについて、体系的にまとめられた情報はなかなか見つからないものです。

本記事では、Vite の主要な設定オプションを辞書形式で整理し、各オプションの役割と使用方法を詳しく解説します。開発現場ですぐに活用できる実践的な情報をお届けしますので、ぜひブックマークしてご活用ください。

設定オプション早見表

以下の表で、本記事で解説する主要な設定オプションを一覧できます:

カテゴリオプション主な用途重要度設定例
resolvealiasパスエイリアス設定★★★'@': path.resolve('src')
extensions拡張子自動解決★★☆['.js', '.ts', '.vue']
dedupe重複パッケージ除去★★☆['react', 'lodash']
conditionsパッケージ解決条件★☆☆['module', 'browser']
optimizeDepsinclude事前バンドル対象★★★['lodash', 'axios']
excludeバンドル除外対象★★☆['@vitejs​/​plugin-vue']
esbuildOptionsESBuild 詳細設定★★☆{ target: 'es2020' }
force強制再バンドル★☆☆true (デバッグ用)
buildtargetビルドターゲット★★★'es2020' または ['chrome80']
outDir出力先ディレクトリ★★★'dist' または 'build'
assetsDir静的アセット出力先★★☆'static' または 'assets'
minifyミニファイ設定★★☆'esbuild' または 'terser'
rollupOptionsRollup 詳細設定★★★チャンク分割、外部化設定
serverhostホストアドレス★★☆'0.0.0.0' (外部アクセス許可)
portポート番号★★★3000 または process.env.PORT
httpsHTTPS 設定★★☆true または証明書指定
proxyプロキシ設定★★★API サーバー連携
corsCORS 設定★★☆クロスオリジン制御

重要度の目安

  • ★★★ 高: ほぼ全てのプロジェクトで設定推奨
  • ★★☆ 中: プロジェクトの要件に応じて設定
  • ★☆☆ 低: 特定の問題解決や最適化で使用

Vite の設定ファイル(vite.config.js / vite.config.ts)での設定方法から具体的な使用例まで、幅広くカバーしています。

背景

モダンなフロントエンド開発では、ビルドツールの設定が開発効率とアプリケーションパフォーマンスに大きな影響を与えます。Vite は高速な開発サーバーと効率的なビルドシステムを提供しますが、その真価を発揮するには適切な設定が不可欠です。

特に以下の 4 つの設定カテゴリは、Vite プロジェクトの核心部分を担っています:

mermaidflowchart TD
    vite["Vite 設定"] --> resolve["resolve<br/>パス解決"]
    vite --> optimizeDeps["optimizeDeps<br/>依存関係最適化"]
    vite --> build["build<br/>本番ビルド"]
    vite --> server["server<br/>開発サーバー"]

    resolve --> alias["エイリアス設定"]
    resolve --> extensions["拡張子解決"]

    optimizeDeps --> include["事前バンドル"]
    optimizeDeps --> exclude["除外設定"]

    build --> outDir["出力先"]
    build --> minify["最適化"]

    server --> port["ポート設定"]
    server --> proxy["プロキシ設定"]

これらの設定を理解することで、開発体験の向上と最適化されたビルド結果を得ることができます。

課題

Vite の設定オプションに関して、開発者が直面する主な課題は以下の通りです:

情報の分散と複雑さ

Vite の公式ドキュメントは充実していますが、実際の開発現場で必要な設定例や組み合わせパターンを見つけるのに時間がかかります。また、各オプションの相互関係や最適な設定値についての情報が分散しています。

設定の優先順位の不明確さ

どの設定オプションを優先して設定すべきか、初心者にとっては判断が困難です。また、設定の変更がどのような影響を与えるかを事前に把握するのも難しい状況です。

バージョン間の差異

Vite のバージョンアップに伴い、一部のオプションが非推奨になったり、新しいオプションが追加されたりしています。最新の情報にキャッチアップするのが困難です。

mermaidflowchart LR
    challenge["設定の課題"] --> scattered["情報の分散"]
    challenge --> priority["優先順位不明"]
    challenge --> version["バージョン差異"]

    scattered --> time["設定時間増加"]
    priority --> confusion["設定ミス"]
    version --> outdated["古い設定"]

    time --> efficiency["開発効率低下"]
    confusion --> efficiency
    outdated --> efficiency

解決策

本記事では、Vite の主要設定オプションを体系的に整理し、実践的な活用方法を提示します。辞書形式で各オプションを詳しく解説することで、必要な情報を素早く見つけられるようにしています。

以下の方針で情報を整理しています:

  • カテゴリ別の体系的整理: resolve、optimizeDeps、build、server の 4 つの主要カテゴリに分けて解説
  • 実践的なコード例: 各オプションに具体的な設定例とコメントを付与
  • 相互関係の明示: オプション間の依存関係や組み合わせパターンを明確化
  • パフォーマンス影響の解説: 各設定がビルド速度や実行時パフォーマンスに与える影響を説明

resolve オプション

resolve オプションは、モジュールの解決方法を制御する重要な設定です。パスエイリアスや拡張子の自動解決など、開発効率に直結する機能を提供します。

alias

モジュールのパスにエイリアスを設定し、インポート文を簡潔にします。

基本的な設定

javascript// vite.config.js
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      // @ を src ディレクトリのエイリアスとして設定
      '@': path.resolve(__dirname, 'src'),
      // components ディレクトリのエイリアス
      '@components': path.resolve(
        __dirname,
        'src/components'
      ),
      // utils ディレクトリのエイリアス
      '@utils': path.resolve(__dirname, 'src/utils'),
    },
  },
});

TypeScript プロジェクトでの設定

TypeScript を使用している場合は、tsconfig.json でも対応するパス設定が必要です:

json{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

使用例

エイリアス設定後は、以下のようにインポートを簡潔に記述できます:

javascript// エイリアス設定前
import Button from '../../../components/ui/Button.vue';
import { formatDate } from '../../../utils/date.js';

// エイリアス設定後
import Button from '@components/ui/Button.vue';
import { formatDate } from '@utils/date.js';

パフォーマンスへの影響

  • ビルド時間: エイリアス解決による若干のオーバーヘッドがありますが、実用上問題ありません
  • 開発体験: パスの記述が簡潔になり、ファイル移動時の修正作業が軽減されます
  • 保守性: プロジェクト構造の変更に対する柔軟性が向上します

extensions

ファイルの拡張子を自動解決する設定です。インポート時に拡張子の記述を省略できます。

デフォルト設定

javascriptexport default defineConfig({
  resolve: {
    // Vite のデフォルト拡張子設定
    extensions: [
      '.mjs',
      '.js',
      '.mts',
      '.ts',
      '.jsx',
      '.tsx',
      '.json',
    ],
  },
});

カスタム拡張子の追加

javascriptexport default defineConfig({
  resolve: {
    extensions: [
      '.mjs',
      '.js',
      '.mts',
      '.ts',
      '.jsx',
      '.tsx',
      '.json',
      // Vue ファイルの拡張子を追加
      '.vue',
      // カスタム拡張子を追加
      '.scss',
      '.css',
    ],
  },
});

使用例

拡張子設定により、以下のような記述が可能になります:

javascript// 拡張子省略前
import Component from './Component.vue';
import styles from './styles.scss';

// 拡張子省略後
import Component from './Component';
import styles from './styles';

注意点

  • 解決順序: 配列の順序に従って拡張子が試行されるため、よく使用する拡張子を前に配置
  • パフォーマンス: 拡張子の候補が多すぎると解決に時間がかかる可能性があります
  • 明示性: 重要なファイルでは拡張子を明示的に記述することも推奨されます

dedupe

同一パッケージの複数バージョンが解決された場合に、重複を除去する設定です。

基本設定

javascriptexport default defineConfig({
  resolve: {
    // 重複排除したいパッケージを指定
    dedupe: ['react', 'react-dom', 'lodash'],
  },
});

実用的な使用例

javascriptexport default defineConfig({
  resolve: {
    dedupe: [
      // React 関連パッケージの重複排除
      'react',
      'react-dom',
      // 大きなユーティリティライブラリの重複排除
      'lodash',
      'moment',
      // UI ライブラリの重複排除
      '@mui/material',
      'antd',
    ],
  },
});

dedupe が必要な場面

パターン説明解決方法
1異なるパッケージが同じ依存関係の異なるバージョンを要求dedupe で統一バージョンを強制
2モノレポ環境での重複解決workspace 全体で dedupe 設定
3peer dependencies の競合明示的な dedupe 指定

パフォーマンス効果

  • バンドルサイズ削減: 重複パッケージの排除により、最終的なバンドルサイズが削減されます
  • 実行時パフォーマンス: 同一機能の重複実行を防ぎ、メモリ使用量を最適化
  • 型安全性: TypeScript 使用時の型競合を回避

conditions

パッケージの conditions フィールドを解決する際の条件を指定します。

デフォルト条件

javascriptexport default defineConfig({
  resolve: {
    // Vite のデフォルト conditions
    conditions: [
      'module',
      'browser',
      'development|production',
    ],
  },
});

カスタム条件の設定

javascriptexport default defineConfig({
  resolve: {
    conditions: [
      'module', // ES modules を優先
      'browser', // ブラウザ環境用のコード
      'import', // import 文での読み込み
      'require', // require での読み込み
      'default', // デフォルト条件
    ],
  },
});

環境別の条件設定

javascriptexport default defineConfig(({ mode }) => ({
  resolve: {
    conditions:
      mode === 'development'
        ? ['development', 'module', 'browser']
        : ['production', 'module', 'browser'],
  },
}));

package.json での exports フィールド例

json{
  "exports": {
    ".": {
      "development": "./dist/index.dev.js",
      "production": "./dist/index.prod.js",
      "module": "./dist/index.esm.js",
      "browser": "./dist/index.browser.js",
      "default": "./dist/index.js"
    }
  }
}

実用的な活用例

conditions の設定により、以下のような最適化が可能です:

  • 開発環境: デバッグ情報付きのバージョンを使用
  • 本番環境: 最適化されたバージョンを使用
  • ブラウザ環境: ブラウザ固有の polyfill を含むバージョンを使用
  • Node.js 環境: サーバーサイド用の最適化されたバージョンを使用

optimizeDeps オプション

optimizeDeps は Vite の依存関係事前バンドル機能を制御します。開発時のパフォーマンス向上とモジュール解決の最適化に重要な役割を果たします。

include

事前バンドルに含めるパッケージを明示的に指定します。動的インポートやコード分割されたパッケージも確実にバンドル対象にできます。

基本的な include 設定

javascriptexport default defineConfig({
  optimizeDeps: {
    // 動的インポートされるパッケージを事前バンドル
    include: [
      'lodash',
      'axios',
      'dayjs',
      // Vue 関連パッケージ
      'vue',
      'vue-router',
      // React 関連パッケージ
      'react',
      'react-dom',
    ],
  },
});

条件付きインポートの対応

javascriptexport default defineConfig({
  optimizeDeps: {
    include: [
      // 条件付きでインポートされるパッケージ
      'chart.js',
      'three',
      // 遅延読み込みされるパッケージ
      'highlight.js',
      'monaco-editor',
    ],
  },
});

Deep Import の処理

javascriptexport default defineConfig({
  optimizeDeps: {
    include: [
      // Deep import されるサブモジュールも明示的に指定
      'lodash/debounce',
      'lodash/throttle',
      'rxjs/operators',
      'date-fns/format',
      'date-fns/parseISO',
    ],
  },
});

効果的な include パターン

| パターン | 使用例 | 効果 | | -------- | ------------------- | ------------------ | ---------------------- | | 1 | 大きなライブラリ | three, echarts | 初回読み込み時間短縮 | | 2 | 条件付き読み込み | monaco-editor | 動的インポート最適化 | | 3 | Deep Import | lodash​/​debounce | 部分的なライブラリ使用 | | 4 | CommonJS モジュール | moment | ESM 変換の事前実行 |

exclude

事前バンドルから除外するパッケージを指定します。不要なバンドルを防ぎ、ビルド時間を短縮できます。

基本的な exclude 設定

javascriptexport default defineConfig({
  optimizeDeps: {
    exclude: [
      // 開発時のみ使用するパッケージ
      'vite',
      '@vitejs/plugin-vue',
      // サーバーサイドでのみ使用
      'fs-extra',
      'path',
      // 既に最適化済みのパッケージ
      '@vueuse/core',
    ],
  },
});

特定条件での exclude

javascriptexport default defineConfig(({ command, mode }) => ({
  optimizeDeps: {
    exclude: [
      // 開発モードでのみ除外
      ...(mode === 'development'
        ? ['@vue/devtools-api']
        : []),
      // テスト環境では除外
      ...(mode === 'test' ? ['@testing-library/vue'] : []),
      // プロダクションビルドでは除外
      ...(command === 'build' ? ['vite-plugin-mock'] : []),
    ],
  },
}));

exclude すべきパッケージの判断基準

javascriptexport default defineConfig({
  optimizeDeps: {
    exclude: [
      // 1. Vite プラグインや開発ツール
      'vite-plugin-*',
      '@vitejs/*',

      // 2. Node.js 専用パッケージ
      'fs',
      'path',
      'os',

      // 3. 大きすぎて事前バンドルが非効率
      'monaco-editor',

      // 4. 既に ES modules として最適化済み
      '@vueuse/core',
      'vue-demi',
    ],
  },
});

exclude の効果測定

exclude 設定の効果を測定するための方法:

javascript// パフォーマンス測定用の設定
export default defineConfig({
  optimizeDeps: {
    exclude: ['target-package'],
    // 事前バンドル情報の出力
    force: true,
  },
  // ビルド分析の有効化
  build: {
    rollupOptions: {
      output: {
        manualChunks: (id) => {
          if (id.includes('target-package')) {
            return 'excluded-package';
          }
        },
      },
    },
  },
});

esbuildOptions

ESBuild の詳細設定をカスタマイズし、事前バンドルプロセスを制御します。

基本的な esbuildOptions 設定

javascriptexport default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      // ターゲット環境の指定
      target: 'es2020',
      // サポートする文法機能
      supported: {
        bigint: true,
        'dynamic-import': true,
      },
    },
  },
});

詳細なトランスパイル設定

javascriptexport default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      // JavaScript のバージョン指定
      target: ['es2020', 'chrome80', 'firefox78'],

      // JSX のトランスパイル設定
      jsx: 'automatic',
      jsxFactory: 'React.createElement',
      jsxFragment: 'React.Fragment',

      // TypeScript 設定
      tsconfigRaw: {
        compilerOptions: {
          experimentalDecorators: true,
          emitDecoratorMetadata: true,
        },
      },
    },
  },
});

プラグインの追加

javascriptimport { defineConfig } from 'vite';

export default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      plugins: [
        // カスタム ESBuild プラグイン
        {
          name: 'custom-loader',
          setup(build) {
            // .custom ファイルの処理
            build.onResolve(
              { filter: /\.custom$/ },
              (args) => ({
                path: args.path,
                namespace: 'custom',
              })
            );

            build.onLoad(
              { filter: /.*/, namespace: 'custom' },
              (args) => ({
                contents: '/* カスタム処理 */',
                loader: 'js',
              })
            );
          },
        },
      ],
    },
  },
});

環境変数の定義

javascriptexport default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      // グローバル変数の定義
      define: {
        'process.env.NODE_ENV': '"development"',
        global: 'globalThis',
        __DEV__: 'true',
      },
    },
  },
});

パフォーマンス最適化設定

javascriptexport default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      // 最小化の無効化(開発時のデバッグ用)
      minify: false,

      // ソースマップの生成
      sourcemap: true,

      // Tree shaking の設定
      treeShaking: true,

      // バンドル分析情報の出力
      metafile: true,
    },
  },
});

force

依存関係の事前バンドルを強制的に再実行する設定です。キャッシュ問題の解決やデバッグに使用します。

基本的な force 設定

javascriptexport default defineConfig({
  optimizeDeps: {
    // 事前バンドルキャッシュを無視して強制実行
    force: true,
  },
});

条件付き force 設定

javascriptexport default defineConfig(({ mode }) => ({
  optimizeDeps: {
    // 開発モードでのみ force を有効化
    force: mode === 'development',

    // または環境変数による制御
    force: process.env.VITE_FORCE_OPTIMIZE === 'true',
  },
}));

CI/CD 環境での活用

javascript// CI 環境での確実なビルドのため
export default defineConfig({
  optimizeDeps: {
    force: process.env.CI === 'true',
    include: [
      // CI で確実にバンドルしたいパッケージ
      'react',
      'react-dom',
      'lodash',
    ],
  },
});

force を使用すべき場面

場面説明解決方法
1依存関係の更新後force: true で再バンドル
2キャッシュ破損の疑いforce + キャッシュクリア
3新しいパッケージ追加後一時的な force 有効化
4開発環境の不具合force での問題切り分け

パフォーマンスへの影響

javascriptexport default defineConfig({
  optimizeDeps: {
    // 本番環境では force を無効化
    force: process.env.NODE_ENV !== 'production',

    // force 使用時の最適化
    esbuildOptions: {
      // 並列処理の最大数を制限
      logLevel: 'info',
      // 詳細なログ出力で問題を特定
      logLimit: 0,
    },
  },
});

force 設定の注意点:

  • 開発効率: force は初回ビルド時間を延長するため、通常は無効にしておく
  • デバッグ用途: 問題の特定や新しい設定のテスト時に一時的に有効化
  • 自動化: package.json の scripts で force オプション付きの開発コマンドを用意

build オプション

build オプションは本番環境向けのビルド設定を制御します。出力先の指定から最適化設定まで、アプリケーションの最終的な品質とパフォーマンスを決定する重要な設定群です。

target

ビルドのターゲット環境を指定し、使用する JavaScript の機能レベルを制御します。

基本的な target 設定

javascriptexport default defineConfig({
  build: {
    // モダンブラウザをターゲット
    target: 'es2020',

    // または具体的なブラウザバージョン
    target: ['chrome80', 'firefox78', 'safari14', 'edge88'],
  },
});

複数ターゲットでのビルド

javascriptexport default defineConfig({
  build: {
    target: [
      'es2015', // 古いブラウザサポート
      'chrome64', // Chrome 64+
      'firefox60', // Firefox 60+
      'safari12', // Safari 12+
      'edge79', // Edge 79+
    ],
  },
});

環境別の target 設定

javascriptexport default defineConfig(({ mode }) => ({
  build: {
    target:
      mode === 'legacy'
        ? [
            'es5',
            'chrome49',
            'firefox44',
            'safari10',
            'edge13',
          ]
        : [
            'es2020',
            'chrome80',
            'firefox78',
            'safari14',
            'edge88',
          ],
  },
}));

Node.js 環境向けの設定

javascriptexport default defineConfig({
  build: {
    // SSR や Node.js アプリケーション向け
    target: 'node14',

    // ライブラリビルド向け
    lib: {
      entry: './src/index.ts',
      formats: ['es', 'cjs'],
    },

    rollupOptions: {
      external: ['fs', 'path', 'os'],
    },
  },
});

target 設定の影響範囲

設定値対応機能バンドルサイズパフォーマンス
es5古いブラウザ対応大きいpolyfill 必要
es2015基本的な ES6 機能中程度適度な最適化
es2020モダン機能小さい高いパフォーマンス
esnext最新機能最小最高のパフォーマンス

outDir

ビルド結果の出力先ディレクトリを指定します。

基本的な outDir 設定

javascriptexport default defineConfig({
  build: {
    // デフォルトは 'dist'
    outDir: 'build',

    // プロジェクト構造に応じた設定
    outDir: './public/assets',
  },
});

環境別の出力先設定

javascriptexport default defineConfig(({ mode }) => ({
  build: {
    outDir:
      mode === 'production'
        ? 'dist/production'
        : 'dist/staging',
  },
}));

モノレポでの outDir 設定

javascript// packages/web/vite.config.js
export default defineConfig({
  build: {
    // モノレポ構造に対応した出力先
    outDir: '../../dist/web',

    // 出力先のクリーニング
    emptyOutDir: true,
  },
});

動的な outDir 設定

javascriptimport { defineConfig } from 'vite';
import { resolve } from 'path';

export default defineConfig(({ mode, command }) => {
  // ブランチ名やバージョンを含む出力先
  const branchName = process.env.GIT_BRANCH || 'main';
  const version =
    process.env.npm_package_version || '1.0.0';

  return {
    build: {
      outDir: `dist/${mode}-${branchName}-${version}`,

      // 既存の出力先をクリア
      emptyOutDir: true,
    },
  };
});

Docker 環境での outDir 設定

javascriptexport default defineConfig({
  build: {
    // Docker ボリュームマウント先に対応
    outDir: process.env.DOCKER_OUTPUT_DIR || 'dist',

    // 権限の問題を回避
    emptyOutDir: false,
  },
});

assetsDir

静的アセット(CSS、画像、フォントなど)の出力サブディレクトリを指定します。

基本的な assetsDir 設定

javascriptexport default defineConfig({
  build: {
    // デフォルトは 'assets'
    assetsDir: 'static',

    // より詳細な分類
    assetsDir: 'assets/static',
  },
});

CDN 配信を考慮した設定

javascriptexport default defineConfig({
  build: {
    // CDN のパス構造に合わせた設定
    assetsDir: 'cdn/v1',

    rollupOptions: {
      output: {
        // ファイルタイプ別の詳細制御
        assetFileNames: (assetInfo) => {
          const info = assetInfo.name.split('.');
          const ext = info[info.length - 1];

          if (/\.(css)$/.test(assetInfo.name)) {
            return `css/[name]-[hash].${ext}`;
          }
          if (
            /\.(png|jpe?g|svg|gif|webp|ico)$/.test(
              assetInfo.name
            )
          ) {
            return `images/[name]-[hash].${ext}`;
          }
          if (
            /\.(woff2?|eot|ttf|otf)$/.test(assetInfo.name)
          ) {
            return `fonts/[name]-[hash].${ext}`;
          }

          return `${assetsDir}/[name]-[hash].${ext}`;
        },
      },
    },
  },
});

大きなアセットの分離

javascriptexport default defineConfig({
  build: {
    assetsDir: 'assets',

    rollupOptions: {
      output: {
        manualChunks: {
          // 大きなライブラリを分離
          vendor: ['react', 'react-dom'],
          ui: ['@mui/material', '@emotion/react'],
        },

        assetFileNames: (assetInfo) => {
          // 大きなアセットは別ディレクトリに
          if (assetInfo.size && assetInfo.size > 100000) {
            return 'large-assets/[name]-[hash][extname]';
          }
          return 'assets/[name]-[hash][extname]';
        },
      },
    },
  },
});

キャッシュ戦略との連携

javascriptexport default defineConfig({
  build: {
    assetsDir: 'static',

    rollupOptions: {
      output: {
        // キャッシュ効率を考慮したファイル名
        chunkFileNames: 'js/[name]-[hash].js',
        assetFileNames: (assetInfo) => {
          // 頻繁に更新されるファイルとそうでないファイルを分離
          if (/\.(css)$/.test(assetInfo.name)) {
            return 'css/[name]-[hash][extname]';
          }
          if (
            /\.(woff2?|eot|ttf|otf)$/.test(assetInfo.name)
          ) {
            // フォントは長期キャッシュ
            return 'fonts/[name]-[contenthash][extname]';
          }
          return 'assets/[name]-[hash][extname]';
        },
      },
    },
  },
});

minify

JavaScript と CSS のミニファイ(圧縮)設定を制御します。

基本的な minify 設定

javascriptexport default defineConfig({
  build: {
    // デフォルトは 'esbuild'
    minify: 'esbuild',

    // Terser を使用する場合
    minify: 'terser',

    // ミニファイを無効化(デバッグ用)
    minify: false,
  },
});

Terser の詳細設定

javascriptexport default defineConfig({
  build: {
    minify: 'terser',
    terserOptions: {
      // コメントの削除
      format: {
        comments: false,
      },

      // 圧縮オプション
      compress: {
        // console.log の削除
        drop_console: true,
        // debugger の削除
        drop_debugger: true,
        // 未使用変数の削除
        unused: true,
        // Dead code の削除
        dead_code: true,
      },

      // 難読化オプション
      mangle: {
        // プロパティ名の難読化
        properties: {
          regex: /^_/,
        },
      },
    },
  },
});

環境別の minify 設定

javascriptexport default defineConfig(({ mode }) => ({
  build: {
    minify: mode === 'production' ? 'esbuild' : false,

    // 開発用ビルドでは読みやすさを優先
    ...(mode !== 'production' && {
      rollupOptions: {
        output: {
          format: 'es',
          preserveModules: true,
        },
      },
    }),
  },
}));

ライブラリビルド時の minify 設定

javascriptexport default defineConfig({
  build: {
    lib: {
      entry: './src/index.ts',
      formats: ['es', 'cjs', 'umd'],
    },

    // ライブラリでは利用者が選択できるよう非圧縮版も提供
    minify: false,

    rollupOptions: {
      output: [
        {
          format: 'es',
          entryFileNames: '[name].es.js',
        },
        {
          format: 'es',
          entryFileNames: '[name].es.min.js',
          plugins: [
            // 圧縮版のみ Terser を適用
            require('rollup-plugin-terser').terser(),
          ],
        },
      ],
    },
  },
});

パフォーマンス比較

ミニファイア圧縮率速度特徴
esbuild良好非常に高速Go 製、デフォルト
terser優秀中程度高度な設定可能
無効なし最高速デバッグ用

rollupOptions

Rollup の詳細設定を制御し、高度なビルドカスタマイズを行います。

基本的な rollupOptions 設定

javascriptexport default defineConfig({
  build: {
    rollupOptions: {
      // 外部依存関係の指定
      external: ['react', 'react-dom'],

      // 出力設定
      output: {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM',
        },
      },
    },
  },
});

チャンク分割の詳細制御

javascriptexport default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // ベンダーライブラリを分離
          vendor: [
            'react',
            'react-dom',
            'react-router-dom',
          ],

          // UI コンポーネントライブラリ
          ui: [
            '@mui/material',
            '@emotion/react',
            '@emotion/styled',
          ],

          // ユーティリティライブラリ
          utils: ['lodash', 'date-fns', 'axios'],

          // 大きなライブラリは個別に分離
          charts: ['chart.js', 'echarts'],
          editor: ['monaco-editor'],
        },

        // 動的チャンク分割
        manualChunks: (id) => {
          // node_modules のパッケージ
          if (id.includes('node_modules')) {
            // 大きなパッケージは個別チャンク
            if (id.includes('monaco-editor'))
              return 'monaco';
            if (id.includes('echarts')) return 'echarts';
            if (id.includes('@mui')) return 'mui';

            // その他は vendor チャンク
            return 'vendor';
          }

          // ページ別の分割
          if (id.includes('/pages/')) {
            const page = id
              .split('/pages/')[1]
              .split('/')[0];
            return `page-${page}`;
          }
        },
      },
    },
  },
});

プラグインの追加

javascriptimport { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  build: {
    rollupOptions: {
      plugins: [
        // バンドル分析
        visualizer({
          filename: 'dist/stats.html',
          open: true,
          gzipSize: true,
        }),

        // カスタムプラグイン
        {
          name: 'custom-plugin',
          generateBundle(options, bundle) {
            // ビルド後の処理
            console.log(
              'Generated chunks:',
              Object.keys(bundle)
            );
          },
        },
      ],
    },
  },
});

SSR 対応の設定

javascriptexport default defineConfig({
  build: {
    rollupOptions: {
      // SSR ビルド用の設定
      input: {
        client: './src/entry-client.js',
        server: './src/entry-server.js',
      },

      output: {
        // サーバー用ビルドでは CJS 形式
        format: 'cjs',

        // クライアント用とサーバー用で出力先を分離
        dir: 'dist',
        entryFileNames: (chunk) => {
          return chunk.name === 'server'
            ? 'server/[name].js'
            : 'client/[name]-[hash].js';
        },
      },

      // サーバーサイドでは Node.js モジュールを外部化
      external: (id) => {
        return !id.startsWith('.') && !id.startsWith('/');
      },
    },
  },
});

パフォーマンス最適化設定

javascriptexport default defineConfig({
  build: {
    rollupOptions: {
      // 最適化オプション
      treeshake: {
        // より積極的な tree shaking
        moduleSideEffects: false,
        propertyReadSideEffects: false,
        unknownGlobalSideEffects: false,
      },

      output: {
        // 実行時最適化
        hoistTransitiveImports: false,

        // チャンクサイズの制御
        maxParallelFileOps: 5,

        // ファイル名のハッシュ化
        entryFileNames: 'js/[name]-[hash].js',
        chunkFileNames: 'js/[name]-[hash].js',
        assetFileNames: 'assets/[name]-[hash][extname]',
      },
    },
  },
});

rollupOptions の設定により、以下のような最適化が可能です:

  • バンドルサイズの最適化: 適切なチャンク分割によるロード時間短縮
  • キャッシュ効率の向上: ハッシュベースのファイル名による長期キャッシュ
  • 並列読み込み: 依存関係に基づく効率的なリソース読み込み
  • Tree Shaking: 未使用コードの除去によるサイズ削減

server オプション

server オプションは Vite の開発サーバーの動作を制御します。ポート設定からプロキシ機能まで、開発体験に直結する重要な設定群です。

host

開発サーバーがバインドするホストアドレスを指定します。

基本的な host 設定

javascriptexport default defineConfig({
  server: {
    // ローカルのみアクセス可能(デフォルト)
    host: 'localhost',

    // 外部からのアクセスを許可
    host: '0.0.0.0',

    // 特定の IP アドレスを指定
    host: '192.168.1.100',
  },
});

環境別の host 設定

javascriptexport default defineConfig(({ mode }) => ({
  server: {
    host:
      mode === 'development'
        ? 'localhost' // 開発時はローカルのみ
        : '0.0.0.0', // ステージング等では外部アクセス許可
  },
}));

Docker コンテナでの設定

javascriptexport default defineConfig({
  server: {
    // Docker コンテナ内では 0.0.0.0 が必須
    host: process.env.DOCKER ? '0.0.0.0' : 'localhost',

    // ポートも Docker 環境に合わせて設定
    port: process.env.PORT || 3000,
  },
});

モバイル開発での設定

javascriptexport default defineConfig({
  server: {
    // モバイル端末からのアクセスを許可
    host: '0.0.0.0',

    // QR コード生成での URL 表示
    open: false,

    // ネットワーク情報の表示
    strictPort: false,
  },
});

セキュリティを考慮した設定

javascriptexport default defineConfig({
  server: {
    // 本番環境では絶対に 0.0.0.0 を使用しない
    host:
      process.env.NODE_ENV === 'production'
        ? '127.0.0.1' // ローカルのみ
        : '0.0.0.0', // 開発時は外部アクセス許可

    // HTTPS 強制(本番相当環境)
    https: process.env.NODE_ENV !== 'development',
  },
});

port

開発サーバーのポート番号を指定します。

基本的な port 設定

javascriptexport default defineConfig({
  server: {
    // デフォルトは 5173
    port: 3000,

    // ポートが使用中の場合は自動で次のポートを使用
    strictPort: false,
  },
});

環境変数による port 設定

javascriptexport default defineConfig({
  server: {
    // 環境変数からポートを取得、デフォルトは 3000
    port: parseInt(process.env.PORT) || 3000,

    // CI 環境では厳密なポート指定
    strictPort: process.env.CI === 'true',
  },
});

マイクロサービス環境での port 設定

javascript// 複数のサービスを同時に起動する場合の設定
export default defineConfig({
  server: {
    port:
      {
        frontend: 3000,
        admin: 3001,
        'api-gateway': 3002,
      }[process.env.SERVICE_NAME] || 3000,

    strictPort: true, // ポート競合を避けるため厳密指定
  },
});

ポート範囲の指定

javascriptexport default defineConfig({
  server: {
    // 利用可能なポート範囲から自動選択
    port:
      process.env.PORT ||
      (() => {
        const basePort = 3000;
        const maxAttempts = 10;

        for (let i = 0; i < maxAttempts; i++) {
          const port = basePort + i;
          // ポートの可用性チェック(実装は簡略化)
          return port;
        }

        throw new Error('利用可能なポートが見つかりません');
      })(),
  },
});

開発チーム間でのポート管理

javascript// package.json での設定例
{
  "scripts": {
    "dev:frontend": "PORT=3000 vite",
    "dev:admin": "PORT=3001 vite --config vite.admin.config.js",
    "dev:mobile": "PORT=3002 vite --config vite.mobile.config.js"
  }
}

// vite.config.js
export default defineConfig({
  server: {
    port: parseInt(process.env.PORT) || 5173,

    // ポート衝突の回避
    strictPort: true,

    // 開発チーム用の設定
    open: process.env.AUTO_OPEN !== 'false'
  }
})

https

HTTPS での開発サーバー起動設定を制御します。

基本的な https 設定

javascriptexport default defineConfig({
  server: {
    // 自己署名証明書で HTTPS を有効化
    https: true,

    // 無効化
    https: false,
  },
});

カスタム証明書の使用

javascriptimport fs from 'fs';

export default defineConfig({
  server: {
    https: {
      // カスタム証明書ファイルを指定
      key: fs.readFileSync('./certs/localhost-key.pem'),
      cert: fs.readFileSync('./certs/localhost.pem'),
    },
  },
});

mkcert を使用した証明書設定

javascript// 事前に mkcert で証明書を生成
// $ mkcert localhost 127.0.0.1 ::1

export default defineConfig({
  server: {
    https: {
      key: './certs/localhost+2-key.pem',
      cert: './certs/localhost+2.pem',
    },

    // HTTPS 使用時の自動ブラウザ起動
    open: 'https://localhost:3000',
  },
});

条件付き HTTPS 設定

javascriptexport default defineConfig(({ mode }) => {
  const useHttps =
    mode === 'staging' ||
    process.env.HTTPS === 'true' ||
    process.env.NODE_ENV === 'production';

  return {
    server: {
      https: useHttps
        ? {
            // 本番に近い環境では適切な証明書を使用
            key: process.env.SSL_KEY_PATH,
            cert: process.env.SSL_CERT_PATH,
          }
        : false,

      // HTTPS 使用時のリダイレクト設定
      ...(useHttps && {
        middlewares: [
          (req, res, next) => {
            if (
              req.headers['x-forwarded-proto'] !== 'https'
            ) {
              res.redirect(
                `https://${req.headers.host}${req.url}`
              );
            } else {
              next();
            }
          },
        ],
      }),
    },
  };
});

PWA 開発での HTTPS 設定

javascriptexport default defineConfig({
  server: {
    // PWA では Service Worker のため HTTPS が必要
    https: true,

    // ローカル開発での証明書エラーを無視
    hmr: {
      // HMR も HTTPS で動作
      port: 24678,
    },
  },

  // PWA プラグインとの連携
  plugins: [
    // ... PWA プラグイン設定
  ],
});

proxy

API サーバーとの連携や CORS 問題の解決のためのプロキシ設定を行います。

基本的な proxy 設定

javascriptexport default defineConfig({
  server: {
    proxy: {
      // /api で始まるリクエストを別サーバーにプロキシ
      '/api': 'http://localhost:8080',

      // より詳細な設定
      '/api/v2': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) =>
          path.replace(/^\/api\/v2/, '/api'),
      },
    },
  },
});

複数 API サーバーへのプロキシ

javascriptexport default defineConfig({
  server: {
    proxy: {
      // ユーザー関連 API
      '/api/users': {
        target: 'http://user-service:3001',
        changeOrigin: true,
      },

      // 商品関連 API
      '/api/products': {
        target: 'http://product-service:3002',
        changeOrigin: true,
      },

      // 認証関連 API
      '/api/auth': {
        target: 'http://auth-service:3003',
        changeOrigin: true,
        // 認証ヘッダーの追加
        configure: (proxy, options) => {
          proxy.on('proxyReq', (proxyReq, req, res) => {
            proxyReq.setHeader(
              'X-Special-Proxy-Header',
              'foobar'
            );
          });
        },
      },
    },
  },
});

WebSocket のプロキシ設定

javascriptexport default defineConfig({
  server: {
    proxy: {
      // WebSocket 接続のプロキシ
      '/socket.io': {
        target: 'ws://localhost:8080',
        ws: true,
        changeOrigin: true,
      },

      // GraphQL Subscription のプロキシ
      '/graphql-ws': {
        target: 'ws://localhost:4000',
        ws: true,
        changeOrigin: true,
        configure: (proxy, options) => {
          proxy.on('error', (err, req, res) => {
            console.log('WebSocket proxy error:', err);
          });
        },
      },
    },
  },
});

条件付きプロキシ設定

javascriptexport default defineConfig(({ mode }) => ({
  server: {
    proxy: {
      '/api': {
        // 環境に応じてプロキシ先を変更
        target:
          {
            development: 'http://localhost:8080',
            staging: 'https://staging-api.example.com',
            production: 'https://api.example.com',
          }[mode] || 'http://localhost:8080',

        changeOrigin: true,

        // 開発環境でのみログ出力
        configure: (proxy, options) => {
          if (mode === 'development') {
            proxy.on('proxyReq', (proxyReq, req, res) => {
              console.log('Proxying:', req.method, req.url);
            });
          }
        },
      },
    },
  },
}));

認証付きプロキシの設定

javascriptexport default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        configure: (proxy, options) => {
          proxy.on('proxyReq', (proxyReq, req, res) => {
            // 開発用の認証トークンを自動で追加
            const devToken = process.env.DEV_AUTH_TOKEN;
            if (devToken) {
              proxyReq.setHeader(
                'Authorization',
                `Bearer ${devToken}`
              );
            }

            // CSRF トークンの処理
            if (req.headers['x-csrf-token']) {
              proxyReq.setHeader(
                'X-CSRF-Token',
                req.headers['x-csrf-token']
              );
            }
          });

          proxy.on('proxyRes', (proxyRes, req, res) => {
            // レスポンスヘッダーの調整
            proxyRes.headers[
              'Access-Control-Allow-Origin'
            ] = '*';
            proxyRes.headers[
              'Access-Control-Allow-Credentials'
            ] = 'true';
          });
        },
      },
    },
  },
});

cors

Cross-Origin Resource Sharing (CORS) の設定を制御します。

基本的な cors 設定

javascriptexport default defineConfig({
  server: {
    // 全てのオリジンを許可(開発時のみ)
    cors: true,

    // CORS を無効化
    cors: false,
  },
});

詳細な cors 設定

javascriptexport default defineConfig({
  server: {
    cors: {
      // 許可するオリジン
      origin: [
        'http://localhost:3000',
        'http://localhost:3001',
        'https://example.com',
      ],

      // 許可する HTTP メソッド
      methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],

      // 許可するヘッダー
      allowedHeaders: [
        'Content-Type',
        'Authorization',
        'X-Requested-With',
        'X-CSRF-Token',
      ],

      // Cookie の送信を許可
      credentials: true,

      // プリフライトリクエストのキャッシュ時間
      maxAge: 86400,
    },
  },
});

環境別の cors 設定

javascriptexport default defineConfig(({ mode }) => ({
  server: {
    cors:
      mode === 'development'
        ? {
            // 開発環境では緩い設定
            origin: true,
            credentials: true,
          }
        : {
            // 本番環境では厳密な設定
            origin: [
              'https://yourdomain.com',
              'https://admin.yourdomain.com',
            ],
            credentials: true,
            methods: ['GET', 'POST', 'PUT', 'DELETE'],
            allowedHeaders: [
              'Content-Type',
              'Authorization',
            ],
          },
  },
}));

動的な CORS 設定

javascriptexport default defineConfig({
  server: {
    cors: {
      origin: (origin, callback) => {
        // 許可するドメインのリスト
        const allowedOrigins = [
          'http://localhost:3000',
          'https://example.com',
          // 環境変数から追加ドメインを取得
          ...(process.env.ALLOWED_ORIGINS?.split(',') ||
            []),
        ];

        // オリジンが許可リストに含まれているかチェック
        if (!origin || allowedOrigins.includes(origin)) {
          callback(null, true);
        } else {
          callback(
            new Error(
              'CORS エラー: 許可されていないオリジンです'
            )
          );
        }
      },

      credentials: true,

      // カスタムヘッダーの処理
      exposedHeaders: [
        'X-Total-Count',
        'X-RateLimit-Remaining',
      ],
    },
  },
});

マイクロフロントエンド環境での CORS 設定

javascriptexport default defineConfig({
  server: {
    cors: {
      // 複数のマイクロフロントエンドからのアクセスを許可
      origin: [
        'http://localhost:3000', // Shell アプリケーション
        'http://localhost:3001', // ユーザー管理マイクロフロントエンド
        'http://localhost:3002', // 商品管理マイクロフロントエンド
        'http://localhost:3003', // 分析ダッシュボード
      ],

      credentials: true,

      // カスタムヘッダーでマイクロフロントエンド識別
      allowedHeaders: [
        'Content-Type',
        'Authorization',
        'X-Microfrontend-Id',
        'X-Shell-Version',
      ],
    },

    // プロキシと CORS の連携
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        configure: (proxy, options) => {
          proxy.on('proxyRes', (proxyRes, req, res) => {
            // プロキシ経由のレスポンスでも CORS ヘッダーを設定
            proxyRes.headers[
              'Access-Control-Allow-Origin'
            ] = req.headers.origin;
            proxyRes.headers[
              'Access-Control-Allow-Credentials'
            ] = 'true';
          });
        },
      },
    },
  },
});

CORS 設定の考慮事項:

  • セキュリティ: 本番環境では必要最小限のオリジンのみを許可
  • 開発効率: 開発環境では柔軟な設定で開発体験を向上
  • パフォーマンス: プリフライトリクエストの最適化でレスポンス時間を改善
  • デバッグ: CORS エラーの詳細なログ出力で問題の特定を容易に

まとめ

本記事では、Vite の主要な設定オプションである resolveoptimizeDepsbuildserver について、辞書形式で詳しく解説しました。

それぞれの設定カテゴリの重要なポイントを振り返ります:

resolve オプションの要点

  • alias: パスエイリアスによる開発効率の向上とコード保守性の改善
  • extensions: 拡張子の自動解決によるインポート文の簡潔化
  • dedupe: 重複パッケージの排除によるバンドルサイズの最適化
  • conditions: パッケージ解決条件の制御による環境別最適化

optimizeDeps オプションの要点

  • include: 動的インポートやコード分割されたパッケージの事前バンドル
  • exclude: 不要なバンドルの回避によるビルド時間の短縮
  • esbuildOptions: ESBuild の詳細カスタマイズによる最適化
  • force: キャッシュ問題の解決とデバッグ用途での活用

build オプションの要点

  • target: ターゲット環境に応じた JavaScript 機能レベルの制御
  • outDir: 柔軟な出力先設定による CI/CD や環境管理の最適化
  • assetsDir: 静的アセットの効率的な分類とキャッシュ戦略
  • minify: 適切な圧縮設定による本番環境のパフォーマンス最適化
  • rollupOptions: 高度なビルドカスタマイズとチャンク分割制御

server オプションの要点

  • host: 開発環境のアクセス制御とセキュリティ考慮
  • port: 環境に応じた柔軟なポート管理
  • https: PWA や API 連携での HTTPS 開発環境構築
  • proxy: API サーバーとの効率的な連携と CORS 問題の解決
  • cors: セキュリティと開発効率を両立したクロスオリジン制御

これらの設定を適切に組み合わせることで、開発体験の向上と本番環境でのパフォーマンス最適化の両方を実現できます。プロジェクトの要件や環境に応じて、段階的に設定を調整していくことをお勧めします。

Vite の設定は継続的な改善が可能な領域です。パフォーマンス測定やビルド分析を定期的に行い、最適な設定を見つけていきましょう。

関連リンク