Skip to content

Commit b2b877a

Browse files
hi-ogawaclaude
andcommitted
refactor(rsc): restructure environmentImportMetaMap to key by sourceEnv
Change from `Record<resolvedId, meta>` to `Record<sourceEnv, Record<resolvedId, meta>>`. This properly handles the case where the same module is imported from multiple source environments, avoiding overwrites. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 0251ac1 commit b2b877a

File tree

2 files changed

+35
-23
lines changed

2 files changed

+35
-23
lines changed

packages/plugin-rsc/src/plugin.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ class RscPluginManager {
125125
{}
126126
serverReferenceMetaMap: Record<string, ServerRerferenceMeta> = {}
127127
serverResourcesMetaMap: Record<string, { key: string }> = {}
128-
environmentImportMetaMap: Record<string, EnvironmentImportMeta> = {}
128+
// Keyed by [sourceEnv][resolvedId] to support same module imported from multiple environments
129+
environmentImportMetaMap: Record<
130+
string,
131+
Record<string, EnvironmentImportMeta>
132+
> = {}
129133

130134
stabilize(): void {
131135
// sort for stable build
@@ -157,17 +161,10 @@ class RscPluginManager {
157161
return
158162
}
159163

160-
// Group imports by source environment
161-
const bySourceEnv: Record<string, typeof this.environmentImportMetaMap> = {}
162-
for (const [resolvedId, meta] of Object.entries(
164+
// Write manifest to each source environment's output
165+
for (const [sourceEnv, imports] of Object.entries(
163166
this.environmentImportMetaMap,
164167
)) {
165-
bySourceEnv[meta.sourceEnv] ??= {}
166-
bySourceEnv[meta.sourceEnv]![resolvedId] = meta
167-
}
168-
169-
// Write manifest to each source environment's output
170-
for (const [sourceEnv, imports] of Object.entries(bySourceEnv)) {
171168
const sourceOutDir = this.config.environments[sourceEnv]!.build.outDir
172169
const manifestPath = path.join(sourceOutDir, ENV_IMPORTS_MANIFEST_NAME)
173170

packages/plugin-rsc/src/plugins/import-environment.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,20 @@ export function vitePluginImportEnvironment(
6262
// Emit discovered entries during build
6363
if (this.environment.mode !== 'build') return
6464

65-
for (const meta of Object.values(manager.environmentImportMetaMap)) {
66-
if (meta.targetEnv === this.environment.name) {
67-
this.emitFile({
68-
type: 'chunk',
69-
id: meta.resolvedId,
70-
})
65+
// Collect unique entries targeting this environment (may be imported from multiple sources)
66+
const emitted = new Set<string>()
67+
for (const imports of Object.values(manager.environmentImportMetaMap)) {
68+
for (const meta of Object.values(imports)) {
69+
if (
70+
meta.targetEnv === this.environment.name &&
71+
!emitted.has(meta.resolvedId)
72+
) {
73+
emitted.add(meta.resolvedId)
74+
this.emitFile({
75+
type: 'chunk',
76+
id: meta.resolvedId,
77+
})
78+
}
7179
}
7280
}
7381
},
@@ -124,11 +132,13 @@ export function vitePluginImportEnvironment(
124132
resolvedId = resolved.id
125133
}
126134

127-
// Track discovered entry (keyed by absolute path for generateBundle lookup)
128-
manager.environmentImportMetaMap[resolvedId] = {
135+
// Track discovered entry, keyed by [sourceEnv][resolvedId]
136+
const sourceEnv = this.environment.name
137+
manager.environmentImportMetaMap[sourceEnv] ??= {}
138+
manager.environmentImportMetaMap[sourceEnv]![resolvedId] = {
129139
resolvedId,
130140
targetEnv: environmentName,
131-
sourceEnv: this.environment.name,
141+
sourceEnv,
132142
specifier,
133143
}
134144

@@ -178,12 +188,17 @@ export function vitePluginImportEnvironment(
178188
if (this.environment.name === 'client') return
179189

180190
// Track output filenames for discovered environment imports
181-
// This runs in both RSC and SSR builds to capture all outputs
191+
// Only set fileName when this bundle's environment matches the target
182192
for (const [fileName, chunk] of Object.entries(bundle)) {
183193
if (chunk.type === 'chunk' && chunk.isEntry && chunk.facadeModuleId) {
184-
const meta = manager.environmentImportMetaMap[chunk.facadeModuleId]
185-
if (meta) {
186-
meta.fileName = fileName
194+
const resolvedId = chunk.facadeModuleId
195+
for (const imports of Object.values(
196+
manager.environmentImportMetaMap,
197+
)) {
198+
const meta = imports[resolvedId]
199+
if (meta && meta.targetEnv === this.environment.name) {
200+
meta.fileName = fileName
201+
}
187202
}
188203
}
189204
}

0 commit comments

Comments
 (0)