Skip to content

Commit f7c422e

Browse files
hi-ogawaclaude
andcommitted
refactor(rsc): use renderChunk to fix manifest import relative paths
Use a placeholder in transform and replace with correct relative path in renderChunk, similar to how BUILD_ASSETS_MANIFEST_NAME is handled. This ensures manifest imports work correctly for nested chunk outputs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fe0e772 commit f7c422e

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

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

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ import MagicString from 'magic-string'
44
import { stripLiteral } from 'strip-literal'
55
import type { Plugin } from 'vite'
66
import type { RscPluginManager } from '../plugin'
7-
import { createVirtualPlugin, normalizeRollupOpitonsInput } from './utils'
7+
import {
8+
createVirtualPlugin,
9+
normalizeRelativePath,
10+
normalizeRollupOpitonsInput,
11+
} from './utils'
812
import { evalValue } from './vite-utils'
913

1014
export const ENV_IMPORTS_MANIFEST_NAME = '__vite_rsc_env_imports_manifest.js'
11-
export const ENV_IMPORTS_ENTRY_FALLBACK =
12-
'virtual:vite-rsc/env-imports-entry-fallback'
15+
16+
const ENV_IMPORTS_MANIFEST_PLACEHOLDER = 'virtual:vite-rsc/env-imports-manifest'
17+
const ENV_IMPORTS_ENTRY_FALLBACK = 'virtual:vite-rsc/env-imports-entry-fallback'
1318

1419
export type EnvironmentImportMeta = {
1520
resolvedId: string
@@ -48,14 +53,9 @@ export function vitePluginImportEnvironment(
4853
},
4954
},
5055
resolveId(source) {
51-
// Mark manifest imports as external during build
52-
// The actual file is generated in buildApp after all builds complete
53-
if (
54-
this.environment.mode === 'build' &&
55-
source.endsWith(ENV_IMPORTS_MANIFEST_NAME)
56-
) {
57-
// TODO: relativity should be enforced via another renderChunk patch
58-
return { id: './' + ENV_IMPORTS_MANIFEST_NAME, external: true }
56+
// Use placeholder as external, renderChunk will replace with correct relative path
57+
if (source === ENV_IMPORTS_MANIFEST_PLACEHOLDER) {
58+
return { id: ENV_IMPORTS_MANIFEST_PLACEHOLDER, external: true }
5959
}
6060
},
6161
buildStart() {
@@ -145,7 +145,8 @@ export function vitePluginImportEnvironment(
145145
} else {
146146
// Build: emit manifest lookup with static import
147147
// The manifest is generated in buildApp after all builds complete
148-
replacement = `(await import(${JSON.stringify('./' + ENV_IMPORTS_MANIFEST_NAME)})).default[${JSON.stringify(resolvedId)}]()`
148+
// Use placeholder that renderChunk will replace with correct relative path
149+
replacement = `(await import(${JSON.stringify(ENV_IMPORTS_MANIFEST_PLACEHOLDER)})).default[${JSON.stringify(resolvedId)}]()`
149150
}
150151

151152
const [start, end] = match.indices![0]!
@@ -161,6 +162,23 @@ export function vitePluginImportEnvironment(
161162
},
162163
},
163164

165+
renderChunk(code, chunk) {
166+
if (code.includes(ENV_IMPORTS_MANIFEST_PLACEHOLDER)) {
167+
const replacement = normalizeRelativePath(
168+
path.relative(
169+
path.join(chunk.fileName, '..'),
170+
ENV_IMPORTS_MANIFEST_NAME,
171+
),
172+
)
173+
code = code.replaceAll(
174+
ENV_IMPORTS_MANIFEST_PLACEHOLDER,
175+
() => replacement,
176+
)
177+
return { code }
178+
}
179+
return
180+
},
181+
164182
generateBundle(_options, bundle) {
165183
if (this.environment.name === 'client') return
166184

0 commit comments

Comments
 (0)