Environment インスタンスの使用
実験的機能
環境 API は実験的です。エコシステムが実験し、それらを基盤として構築できるように、メジャーリリース間での API の安定性は引き続き維持されます。ダウンストリームプロジェクトが新機能を実験し、検証する時間を持った後、将来のメジャーリリースでこれらの新しい API を安定化させる予定です(潜在的な破壊的変更を伴う可能性があります)。
リソース
- フィードバックディスカッション (新しい API に関するフィードバックを収集しています)
- 環境 API PR (新しい API が実装され、レビューされた場所)
ぜひフィードバックをお寄せください。
環境へのアクセス
開発中、開発サーバーで利用可能な環境は server.environments を使用してアクセスできます。
// create the server, or get it from the configureServer hook
const server = await createServer(/* options */)
const clientEnvironment = server.environments.client
clientEnvironment.transformRequest(url)
console.log(server.environments.ssr.moduleGraph)プラグインからも現在の環境にアクセスできます。詳細はプラグインの環境 API を参照してください。
DevEnvironment クラス
開発中、各環境は DevEnvironment クラスのインスタンスです。
class DevEnvironment {
/**
* Unique identifier for the environment in a Vite server.
* By default Vite exposes 'client' and 'ssr' environments.
*/
name: string
/**
* Communication channel to send and receive messages from the
* associated module runner in the target runtime.
*/
hot: NormalizedHotChannel
/**
* Graph of module nodes, with the imported relationship between
* processed modules and the cached result of the processed code.
*/
moduleGraph: EnvironmentModuleGraph
/**
* Resolved plugins for this environment, including the ones
* created using the per-environment `create` hook
*/
plugins: Plugin[]
/**
* Allows to resolve, load, and transform code through the
* environment plugins pipeline
*/
pluginContainer: EnvironmentPluginContainer
/**
* Resolved config options for this environment. Options at the server
* global scope are taken as defaults for all environments, and can
* be overridden (resolve conditions, external, optimizedDeps)
*/
config: ResolvedConfig & ResolvedDevEnvironmentOptions
constructor(
name: string,
config: ResolvedConfig,
context: DevEnvironmentContext,
)
/**
* Resolve the URL to an id, load it, and process the code using the
* plugins pipeline. The module graph is also updated.
*/
async transformRequest(url: string): Promise<TransformResult | null>
/**
* Register a request to be processed with low priority. This is useful
* to avoid waterfalls. The Vite server has information about the
* imported modules by other requests, so it can warmup the module graph
* so the modules are already processed when they are requested.
*/
async warmupRequest(url: string): Promise<void>
}DevEnvironmentContext は以下のようになります。
interface DevEnvironmentContext {
hot: boolean
transport?: HotChannel | WebSocketServer
options?: EnvironmentOptions
remoteRunner?: {
inlineSourceMap?: boolean
}
depsOptimizer?: DepsOptimizer
}そして TransformResult は以下のようになります。
interface TransformResult {
code: string
map: SourceMap | { mappings: '' } | null
etag?: string
deps?: string[]
dynamicDeps?: string[]
}Vite サーバー内の環境インスタンスでは、environment.transformRequest(url) メソッドを使用して URL を処理できます。この関数はプラグインパイプラインを使用して url をモジュール id に解決し、それをロードし(ファイルシステムからファイルを読み込むか、仮想モジュールを実装するプラグインを介して)、そしてコードを変換します。モジュールを変換する際に、インポートやその他のメタデータは、対応するモジュールノードを作成または更新することによって、環境モジュールグラフに記録されます。処理が完了すると、変換結果もモジュールに保存されます。
transformRequest の命名
現在の提案では transformRequest(url) と warmupRequest(url) を使用しており、Vite の現在の API に慣れているユーザーにとって議論や理解が容易になるようにしています。リリース前に、これらの名前もレビューする機会があります。例えば、Rollup のプラグインフックにある context.load(id) に倣い、environment.processModule(url) や environment.loadModule(url) と命名することも考えられます。今のところ、現在の名前を維持し、この議論を後回しにするのが良いと考えています。
分離されたモジュールグラフ
各環境は独立したモジュールグラフを持っています。すべてのモジュールグラフは同じシグネチャを持つため、環境に依存せずにグラフを探索したりクエリしたりするための汎用アルゴリズムを実装できます。hotUpdate は良い例です。ファイルが変更された場合、各環境のモジュールグラフが影響を受けるモジュールを発見し、各環境で独立して HMR を実行するために使用されます。
情報
Vite v5 には、クライアントと SSR のモジュールグラフが混在していました。未処理または無効化されたノードが与えられた場合、それがクライアント、SSR、または両方の環境に対応するかどうかを知ることはできません。モジュールノードには、clientImportedModules や ssrImportedModules (そして両方の結合を返す importedModules) のようにプレフィックスが付いたプロパティがあります。importers には、各モジュールノードについてクライアントと SSR 環境の両方からのすべてのインポーターが含まれます。モジュールノードには transformResult と ssrTransformResult もあります。下位互換性レイヤーにより、エコシステムは非推奨の server.moduleGraph から移行できます。
各モジュールは EnvironmentModuleNode インスタンスで表現されます。モジュールはまだ処理されていない状態でグラフに登録されることがあります(その場合、transformResult は null になります)。importers と importedModules もモジュールが処理された後に更新されます。
class EnvironmentModuleNode {
environment: string
url: string
id: string | null = null
file: string | null = null
type: 'js' | 'css'
importers = new Set<EnvironmentModuleNode>()
importedModules = new Set<EnvironmentModuleNode>()
importedBindings: Map<string, Set<string>> | null = null
info?: ModuleInfo
meta?: Record<string, any>
transformResult: TransformResult | null = null
acceptedHmrDeps = new Set<EnvironmentModuleNode>()
acceptedHmrExports: Set<string> | null = null
isSelfAccepting?: boolean
lastHMRTimestamp = 0
lastInvalidationTimestamp = 0
}environment.moduleGraph は EnvironmentModuleGraph のインスタンスです。
export class EnvironmentModuleGraph {
environment: string
urlToModuleMap = new Map<string, EnvironmentModuleNode>()
idToModuleMap = new Map<string, EnvironmentModuleNode>()
etagToModuleMap = new Map<string, EnvironmentModuleNode>()
fileToModulesMap = new Map<string, Set<EnvironmentModuleNode>>()
constructor(
environment: string,
resolveId: (url: string) => Promise<PartialResolvedId | null>,
)
async getModuleByUrl(
rawUrl: string,
): Promise<EnvironmentModuleNode | undefined>
getModuleById(id: string): EnvironmentModuleNode | undefined
getModulesByFile(file: string): Set<EnvironmentModuleNode> | undefined
onFileChange(file: string): void
onFileDelete(file: string): void
invalidateModule(
mod: EnvironmentModuleNode,
seen: Set<EnvironmentModuleNode> = new Set(),
timestamp: number = monotonicDateNow(),
isHmr: boolean = false,
): void
invalidateAll(): void
async ensureEntryFromUrl(
rawUrl: string,
setIsSelfAccepting = true,
): Promise<EnvironmentModuleNode>
createFileOnlyEntry(file: string): EnvironmentModuleNode
async resolveUrl(url: string): Promise<ResolvedUrl>
updateModuleTransformResult(
mod: EnvironmentModuleNode,
result: TransformResult | null,
): void
getModuleByEtag(etag: string): EnvironmentModuleNode | undefined
}