@@ -2,11 +2,13 @@ import assert from 'node:assert'
22import path from 'node:path'
33import MagicString from 'magic-string'
44import { stripLiteral } from 'strip-literal'
5- import type { Plugin , ResolvedConfig , ViteDevServer } from 'vite'
5+ import type { Plugin } from 'vite'
6+ import type { RscPluginManager } from '../plugin'
67import { evalValue } from './vite-utils'
78
89export const ENV_IMPORTS_MANIFEST_NAME = '__vite_rsc_env_imports_manifest.js'
9- export const ENV_IMPORTS_SCAN_VIRTUAL = 'virtual:vite-rsc/env-imports-scan'
10+ export const ENV_IMPORTS_ENTRY_FALLBACK =
11+ 'virtual:vite-rsc/env-imports-entry-fallbacks'
1012
1113export type EnvironmentImportMeta = {
1214 resolvedId : string
@@ -16,18 +18,32 @@ export type EnvironmentImportMeta = {
1618 entryName : string
1719}
1820
19- interface PluginManager {
20- server : ViteDevServer
21- config : ResolvedConfig
22- isScanBuild : boolean
23- environmentImportMetaMap : Record < string , EnvironmentImportMeta >
24- environmentImportOutputMap : Record < string , string >
25- }
26-
27- export function vitePluginImportEnvironment ( manager : PluginManager ) : Plugin [ ] {
21+ export function vitePluginImportEnvironment (
22+ manager : RscPluginManager ,
23+ ) : Plugin [ ] {
2824 return [
2925 {
3026 name : 'rsc:import-environment' ,
27+ configEnvironment : {
28+ order : 'post' ,
29+ handler ( name , config , _env ) {
30+ if ( name === 'ssr' || name === 'rsc' ) {
31+ // ensure at least one entry since otherwise rollup build fails
32+ if ( ! config . build ?. rollupOptions ?. input ) {
33+ return {
34+ build : {
35+ rollupOptions : {
36+ input : {
37+ __vite_rsc_env_imports_entry_fallback :
38+ ENV_IMPORTS_ENTRY_FALLBACK ,
39+ } ,
40+ } ,
41+ } ,
42+ }
43+ }
44+ }
45+ } ,
46+ } ,
3147 resolveId ( source ) {
3248 // Mark manifest imports as external during build
3349 // The actual file is generated in buildApp after all builds complete
@@ -38,19 +54,18 @@ export function vitePluginImportEnvironment(manager: PluginManager): Plugin[] {
3854 return { id : './' + ENV_IMPORTS_MANIFEST_NAME , external : true }
3955 }
4056 // Virtual scan placeholder for scan builds without entries
41- if ( source === ENV_IMPORTS_SCAN_VIRTUAL ) {
42- return '\0' + ENV_IMPORTS_SCAN_VIRTUAL
57+ if ( source === ENV_IMPORTS_ENTRY_FALLBACK ) {
58+ return '\0' + ENV_IMPORTS_ENTRY_FALLBACK
4359 }
4460 } ,
4561 load ( id ) {
46- // Empty module for scan placeholder
47- if ( id === '\0' + ENV_IMPORTS_SCAN_VIRTUAL ) {
48- return 'export {}'
62+ if ( id === '\0' + ENV_IMPORTS_ENTRY_FALLBACK ) {
63+ return 'export default () => "__vite_rsc_env_imports_entry_fallback"'
4964 }
5065 } ,
5166 buildStart ( ) {
52- // Emit discovered entries in real builds (not scan builds)
53- if ( this . environment . mode !== 'build' || manager . isScanBuild ) return
67+ // Emit discovered entries during build
68+ if ( this . environment . mode !== 'build' ) return
5469
5570 for ( const meta of Object . values ( manager . environmentImportMetaMap ) ) {
5671 if ( meta . targetEnv === this . environment . name ) {
@@ -115,6 +130,7 @@ export function vitePluginImportEnvironment(manager: PluginManager): Plugin[] {
115130 resolvedId = resolved . id
116131 }
117132
133+ // TODO: shouldn't be necessary. replace with internal ID.
118134 // Derive entry name from specifier (e.g., './entry.ssr.tsx' -> 'entry.ssr')
119135 const entryName = deriveEntryName ( specifier )
120136
0 commit comments