プラグイン用環境API
実験的
環境APIは実験的です。エコシステムが実験を行い、その上に構築できるように、Vite 6の間はAPIを安定させます。Vite 7では、これらの新しいAPIを、破壊的変更の可能性を伴って安定させる予定です。
リソース
- 新しいAPIに関するフィードバックを収集しているフィードバックに関するディスカッション。
- 新しいAPIが実装およびレビューされた環境APIのプルリクエスト。
フィードバックをお寄せください。
フックで現在の環境にアクセスする
Vite 6までは2つの環境(`client`と`ssr`)しか存在しなかったため、Vite APIでは`ssr`ブール値で現在の環境を識別するだけで十分でした。プラグインフックは最後のオプションパラメータで`ssr`ブール値を受け取り、いくつかのAPIはモジュールを正しい環境に適切に関連付けるためにオプションの最後の`ssr`パラメータを想定していました(例:`server.moduleGraph.getModuleByUrl(url, { ssr })`)。
設定可能な環境の登場により、プラグインでそのオプションとインスタンスにアクセスするための統一された方法ができました。プラグインフックはコンテキストで`this.environment`を公開するようになり、以前は`ssr`ブール値を想定していたAPIは、適切な環境にスコープされるようになりました(例:`environment.moduleGraph.getModuleByUrl(url)`)。
Viteサーバーには共有プラグインパイプラインがありますが、モジュールが処理される場合は常に特定の環境のコンテキストで行われます。`environment`インスタンスはプラグインコンテキストで利用できます。
プラグインは`environment`インスタンスを使用して、環境の設定(`environment.config`を使用してアクセス可能)に応じてモジュールの処理方法を変更できます。
transform(code, id) {
console.log(this.environment.config.resolve.conditions)
}
フックを使用して新しい環境を登録する
プラグインは`config`フックで新しい環境を追加できます(たとえば、RSC用に個別のモジュールグラフを作成するため)。
config(config: UserConfig) {
config.environments.rsc ??= {}
}
環境を登録するには、空のオブジェクトで十分です。ルートレベルの環境設定からデフォルト値が使用されます。
フックを使用して環境を設定する
`config`フックの実行中は、環境の完全なリストはまだわかっておらず、環境はルートレベルの環境設定からのデフォルト値、または`config.environments`レコードを介した明示的な設定の両方の影響を受ける可能性があります。プラグインは`config`フックを使用してデフォルト値を設定する必要があります。各環境を設定するために、新しい`configEnvironment`フックを使用できます。このフックは、最終的なデフォルトの解決を含む、部分的に解決された設定を使用して各環境に対して呼び出されます。
configEnvironment(name: string, options: EnvironmentOptions) {
if (name === 'rsc') {
options.resolve.conditions = // ...
`hotUpdate`フック
- **タイプ:** `(this: { environment: DevEnvironment }, options: HotUpdateOptions) => Array<EnvironmentModuleNode> | void | Promise<Array<EnvironmentModuleNode> | void>`
- **参照:** HMR API
`hotUpdate`フックを使用すると、プラグインは特定の環境に対してカスタムHMR更新処理を実行できます。ファイルが変更されると、HMRアルゴリズムは`server.environments`の順序に従って各環境に対して順番に実行されるため、`hotUpdate`フックは複数回呼び出されます。フックは次のシグネチャを持つコンテキストオブジェクトを受け取ります。
interface HotUpdateOptions {
type: 'create' | 'update' | 'delete'
file: string
timestamp: number
modules: Array<EnvironmentModuleNode>
read: () => string | Promise<string>
server: ViteDevServer
}
`this.environment`は、ファイルの更新が現在処理されているモジュール実行環境です。
`modules`は、変更されたファイルの影響を受けるこの環境内のモジュールの配列です。単一のファイルが複数の提供モジュールにマップされる場合があるため(例:Vue SFC)、配列になっています。
`read`は、ファイルの内容を返す非同期読み取り関数です。これは、一部のシステムでは、エディターがファイルの更新を完了する前にファイル変更コールバックが速く起動し、直接`fs.readFile`を実行すると空のコンテンツが返されるため、提供されます。渡された読み取り関数は、この動作を正規化します。
フックは以下を選択できます。
影響を受けるモジュールリストをフィルタリングして絞り込み、HMRをより正確にします。
空の配列を返して、完全なリロードを実行します。
jshotUpdate({ modules, timestamp }) { if (this.environment.name !== 'client') return // Invalidate modules manually const invalidatedModules = new Set() for (const mod of modules) { this.environment.moduleGraph.invalidateModule( mod, invalidatedModules, timestamp, true ) } this.environment.hot.send({ type: 'full-reload' }) return [] }
空の配列を返し、クライアントにカスタムイベントを送信することにより、完全なカスタムHMR処理を実行します。
jshotUpdate() { if (this.environment.name !== 'client') return this.environment.hot.send({ type: 'custom', event: 'special-update', data: {} }) return [] }
クライアントコードは、HMR APIを使用して対応するハンドラーを登録する必要があります(これは同じプラグインの`transform`フックによって挿入できます)。
jsif (import.meta.hot) { import.meta.hot.on('special-update', (data) => { // perform custom update }) }
環境別プラグイン
プラグインは、`applyToEnvironment`関数を使用して、適用する環境を定義できます。
const UnoCssPlugin = () => {
// shared global state
return {
buildStart() {
// init per environment state with WeakMap<Environment,Data>
// using this.environment
},
configureServer() {
// use global hooks normally
},
applyToEnvironment(environment) {
// return true if this plugin should be active in this environment,
// or return a new plugin to replace it.
// if the hook is not used, the plugin is active in all environments
},
resolveId(id, importer) {
// only called for environments this plugin apply to
},
}
}
プラグインが環境を認識しておらず、現在の環境でキーが設定されていない状態を持つ場合、`applyToEnvironment`フックを使用すると、簡単に環境ごとに設定できます。
import { nonShareablePlugin } from 'non-shareable-plugin'
export default defineConfig({
plugins: [
{
name: 'per-environment-plugin',
applyToEnvironment(environment) {
return nonShareablePlugin({ outputName: environment.name })
},
},
],
})
Viteは、他のフックが必要ない場合に、これらのケースを簡素化するための`perEnvironmentPlugin`ヘルパーをエクスポートします。
import { nonShareablePlugin } from 'non-shareable-plugin'
export default defineConfig({
plugins: [
perEnvironmentPlugin('per-environment-plugin', (environment) =>
nonShareablePlugin({ outputName: environment.name }),
),
],
})
ビルドフックの環境
開発中と同じ方法で、プラグインフックはビルド中にも`ssr`ブール値の代わりに環境インスタンスを受け取ります。これは、`renderChunk`、`generateBundle`、およびその他のビルド専用のフックでも機能します。
ビルド中の共有プラグイン
Vite 6より前では、プラグインパイプラインは開発中とビルド中で異なる方法で動作していました。
- **開発中:** プラグインは共有されます。
- **ビルド中:** プラグインは各環境で分離されます(異なるプロセス:`vite build`、次に`vite build --ssr`)。
これは、フレームワークがファイルシステムに書き込まれたマニフェストファイルを通じて`client`ビルドと`ssr`ビルド間で状態を共有することを強制しました。Vite 6では、すべての環境を単一のプロセスでビルドするようになったため、プラグインパイプラインと環境間の通信を開発と連携させることができます。
将来のメジャーバージョン(Vite 7または8)では、完全な連携を目指しています。
- **開発とビルドの両方で:** プラグインは共有され、環境ごとのフィルタリングが適用されます。
また、ビルド中に共有される単一の`ResolvedConfig`インスタンスがあり、開発中に`WeakMap<ResolvedConfig, CachedData>`で行ってきたのと同じ方法でアプリのビルドプロセスレベル全体でキャッシュできます。
Vite 6では、後方互換性を維持するために、小さなステップを実行する必要があります。エコシステムプラグインは現在、設定にアクセスするために`environment.config.build`の代わりに`config.build`を使用しているため、デフォルトでは環境ごとに新しい`ResolvedConfig`を作成する必要があります。プロジェクトは、`builder.sharedConfigBuild`を`true`に設定することで、完全な設定とプラグインパイプラインの共有をオプトインできます。
このオプションは、最初はプロジェクトの小さなサブセットでのみ機能するため、プラグインの作成者は、`sharedDuringBuild`フラグを`true`に設定することで、特定のプラグインを共有することをオプトインできます。これにより、通常のプラグインと同様に状態を簡単に共有できます。
function myPlugin() {
// Share state among all environments in dev and build
const sharedState = ...
return {
name: 'shared-plugin',
transform(code, id) { ... },
// Opt-in into a single instance for all environments
sharedDuringBuild: true,
}
}