Featured image of post Viteプラグイン開発:ゼロからプロダクションまで

Viteプラグイン開発:ゼロからプロダクションまで

Viteプラグイン開発を基礎から解説。Plugin API、Rollup互換性、仮想モジュール、HMR統合、設定解決、テスト、npm公開までカバーする完全ガイド。

Viteのプラグインシステムは、ビルドパイプラインを拡張・カスタマイズするための強力な機能です。ファイル形式の変換、ビルド時定数の注入、他ツールとの連携など、Vite Plugin APIはあらゆるニーズに対応します。

Viteのプラグインシステムを理解する

Viteプラグインは、ビルドライフサイクルの特定の時点で実行されるフック関数を持つオブジェクトです。基本形は次の通りです:

import type { Plugin } from 'vite';

export function myPlugin(): Plugin {
  return {
    name: 'my-plugin',
    config(config) {
      return config;
    },
    transform(code, id) {
      if (id.endsWith('.custom')) {
        return { code: `export default ${JSON.stringify(code)}`, map: null };
      }
    },
  };
}

nameはデバッグ用に必須です。enforce: 'pre'または'post'で他のプラグインに対する実行順序を制御できます。


Rollup互換性

ViteのプラグインインターフェースはRollupを拡張したもので、ほとんどのRollupプラグインがそのまま動作します。共通フックにはresolveIdloadtransformbuildEndがあります。Vite固有のフックは開発サーバー機能を追加します:

フック目的フェーズ
config解決前にVite設定を変更Serve + Build
configResolved最終解決済み設定を読み取りServe + Build
configureServer開発サーバーを拡張Serveのみ
handleHotUpdateHMR動作をカスタマイズServeのみ

仮想モジュール

仮想モジュールはビルド時にのみ存在し、ファイルシステムではなくプラグインコードによって生成されます:

const VIRTUAL_MODULE = 'virtual:config';

export function configPlugin(): Plugin {
  return {
    name: 'config-plugin',
    resolveId(id) {
      if (id === VIRTUAL_MODULE) return '\0' + VIRTUAL_MODULE;
    },
    load(id) {
      if (id === '\0' + VIRTUAL_MODULE) {
        return `export default ${JSON.stringify({ apiUrl: process.env.API_URL })}`;
      }
    },
  };
}

\0プレフィックスは解決済み仮想モジュールを示すRollupの慣例です。ポリフィルの注入、ビルド時定数の提供、設定ファイルからのコード生成などに活用できます。


HMR統合

handleHotUpdateフックでHot Module Replacementをカスタマイズできます:

handleHotUpdate({ modules }) {
  if (modules.every(m => m.url.includes('node_modules'))) {
    return []; // HMRを抑制
  }
  return modules;
}

テストと公開

ViteのプログラムAPIを使った統合テスト:

import { build } from 'vite';

const result = await build({
  plugins: [testPlugin({ option: 'value' })],
  logLevel: 'silent',
});

公開時はvite-plugin-*の命名規則に従い、viteをpeerDependenciesに指定し、TypeScriptの型定義を含めます。


ViteのPlugin APIは設計が洗練されており、シンプルな変換から高度な仮想モジュール生成まで幅広く対応します。小さなプラグインから始めて、徐々に機能を拡張していくことをお勧めします。