From 258cdd637d1ee80a3c4571685135e89fe283f3a6 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 10 Dec 2024 17:52:58 +0800 Subject: [PATCH] fix: merge client and ssr values for `pluginContainer.getModuleInfo` (#18895) --- .../vite/src/node/server/mixedModuleGraph.ts | 51 ++++++++++++++++++- .../vite/src/node/server/pluginContainer.ts | 43 +++++++++++++--- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/node/server/mixedModuleGraph.ts b/packages/vite/src/node/server/mixedModuleGraph.ts index 51fdc3ad1d3809..b86c6eb752e783 100644 --- a/packages/vite/src/node/server/mixedModuleGraph.ts +++ b/packages/vite/src/node/server/mixedModuleGraph.ts @@ -13,6 +13,9 @@ import type { * We are going to deprecate these types and we can try to use them back in the future. */ +// same default value of "moduleInfo.meta" as in Rollup +const EMPTY_OBJECT = Object.freeze({}) + export class ModuleNode { _moduleGraph: ModuleGraph _clientModule: EnvironmentModuleNode | undefined @@ -76,6 +79,48 @@ export class ModuleNode { } return importedModules } + _getModuleInfoUnion(prop: 'info'): ModuleInfo | undefined { + const _clientValue = this._clientModule?.[prop] + const _ssrValue = this._ssrModule?.[prop] + + if (_clientValue == null && _ssrValue == null) return undefined + + return new Proxy({} as any, { + get: (_, key: string) => { + // `meta` refers to `ModuleInfo.meta` so we refer to `this.meta` to + // handle the object union between client and ssr + if (key === 'meta') { + return this.meta || EMPTY_OBJECT + } + if (_clientValue) { + if (key in _clientValue) { + return _clientValue[key as keyof ModuleInfo] + } + } + if (_ssrValue) { + if (key in _ssrValue) { + return _ssrValue[key as keyof ModuleInfo] + } + } + }, + }) + } + _getModuleObjectUnion(prop: 'meta'): Record | undefined { + const _clientValue = this._clientModule?.[prop] + const _ssrValue = this._ssrModule?.[prop] + + if (_clientValue == null && _ssrValue == null) return undefined + + const info: Record = {} + if (_ssrValue) { + Object.assign(info, _ssrValue) + } + if (_clientValue) { + Object.assign(info, _clientValue) + } + return info + } + get url(): string { return this._get('url') } @@ -97,11 +142,13 @@ export class ModuleNode { get type(): 'js' | 'css' { return this._get('type') } + // `info` needs special care as it's defined as a proxy in `pluginContainer`, + // so we also merge it as a proxy too get info(): ModuleInfo | undefined { - return this._get('info') + return this._getModuleInfoUnion('info') } get meta(): Record | undefined { - return this._get('meta') + return this._getModuleObjectUnion('meta') } get importers(): Set { return this._getModuleSetUnion('importers') diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index c72fa5b0c27355..616a16a9885c74 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -982,14 +982,41 @@ class PluginContainer { } getModuleInfo(id: string): ModuleInfo | null { - return ( - ( - this.environments.client as DevEnvironment - ).pluginContainer.getModuleInfo(id) || - (this.environments.ssr as DevEnvironment).pluginContainer.getModuleInfo( - id, - ) - ) + const clientModuleInfo = ( + this.environments.client as DevEnvironment + ).pluginContainer.getModuleInfo(id) + const ssrModuleInfo = ( + this.environments.ssr as DevEnvironment + ).pluginContainer.getModuleInfo(id) + + if (clientModuleInfo == null && ssrModuleInfo == null) return null + + return new Proxy({} as any, { + get: (_, key: string) => { + // `meta` refers to `ModuleInfo.meta` of both environments, so we also + // need to merge it here + if (key === 'meta') { + const meta: Record = {} + if (ssrModuleInfo) { + Object.assign(meta, ssrModuleInfo.meta) + } + if (clientModuleInfo) { + Object.assign(meta, clientModuleInfo.meta) + } + return meta + } + if (clientModuleInfo) { + if (key in clientModuleInfo) { + return clientModuleInfo[key as keyof ModuleInfo] + } + } + if (ssrModuleInfo) { + if (key in ssrModuleInfo) { + return ssrModuleInfo[key as keyof ModuleInfo] + } + } + }, + }) } get options(): InputOptions {