1+ import type { ConfigEnv } from "vite" ;
12import * as babel from "../babel" ;
23import { parse as esModuleLexer } from "es-module-lexer" ;
34import { removeExports } from "../remove-exports" ;
@@ -44,38 +45,45 @@ function isClientRouteExport(name: string): name is ClientRouteExport {
4445 return CLIENT_ROUTE_EXPORTS_SET . has ( name as ClientRouteExport ) ;
4546}
4647
48+ type ViteCommand = ConfigEnv [ "command" ] ;
49+
4750export function transformVirtualRouteModules ( {
4851 id,
4952 code,
53+ viteCommand,
5054} : {
5155 id : string ;
5256 code : string ;
57+ viteCommand : ViteCommand ;
5358} ) {
5459 if ( ! id . includes ( "route-module" ) ) {
5560 return ;
5661 }
5762
5863 if ( isVirtualRouteModuleId ( id ) ) {
59- return createVirtualRouteModuleCode ( { id, code } ) ;
64+ return createVirtualRouteModuleCode ( { id, code, viteCommand } ) ;
6065 }
6166
6267 if ( isVirtualServerRouteModuleId ( id ) ) {
6368 return createVirtualServerRouteModuleCode ( { id, code } ) ;
6469 }
6570
6671 if ( isVirtualClientRouteModuleId ( id ) ) {
67- return createVirtualClientRouteModuleCode ( { id, code } ) ;
72+ return createVirtualClientRouteModuleCode ( { id, code, viteCommand } ) ;
6873 }
6974}
7075
7176async function createVirtualRouteModuleCode ( {
7277 id,
7378 code : routeSource ,
79+ viteCommand,
7480} : {
7581 id : string ;
7682 code : string ;
83+ viteCommand : ViteCommand ;
7784} ) {
78- const { staticExports, isServerFirstRoute } = parseRouteExports ( routeSource ) ;
85+ const { staticExports, isServerFirstRoute, hasClientExports } =
86+ parseRouteExports ( routeSource ) ;
7987
8088 const clientModuleId = getVirtualClientModuleId ( id ) ;
8189 const serverModuleId = getVirtualServerModuleId ( id ) ;
@@ -91,6 +99,9 @@ async function createVirtualRouteModuleCode({
9199 code += `export { ${ staticExport } } from "${ serverModuleId } ";\n` ;
92100 }
93101 }
102+ if ( viteCommand === "serve" && ! hasClientExports ) {
103+ code += `export { __ensureClientRouteModuleForHmr } from "${ clientModuleId } ";\n` ;
104+ }
94105 } else {
95106 for ( const staticExport of staticExports ) {
96107 if ( isClientRouteExport ( staticExport ) ) {
@@ -142,11 +153,14 @@ function createVirtualServerRouteModuleCode({
142153function createVirtualClientRouteModuleCode ( {
143154 id,
144155 code : routeSource ,
156+ viteCommand,
145157} : {
146158 id : string ;
147159 code : string ;
160+ viteCommand : ViteCommand ;
148161} ) {
149- const { staticExports, isServerFirstRoute } = parseRouteExports ( routeSource ) ;
162+ const { staticExports, isServerFirstRoute, hasClientExports } =
163+ parseRouteExports ( routeSource ) ;
150164 const exportsToRemove = isServerFirstRoute
151165 ? [ ...SERVER_ONLY_ROUTE_EXPORTS , ...COMPONENT_EXPORTS ]
152166 : SERVER_ONLY_ROUTE_EXPORTS ;
@@ -168,17 +182,25 @@ function createVirtualClientRouteModuleCode({
168182 generatorResult . code += `}\n` ;
169183 }
170184
185+ if ( viteCommand === "serve" && isServerFirstRoute && ! hasClientExports ) {
186+ generatorResult . code += `\nexport const __ensureClientRouteModuleForHmr = true;` ;
187+ }
188+
171189 return generatorResult ;
172190}
173191
174192export function parseRouteExports ( code : string ) {
175193 const [ , exportSpecifiers ] = esModuleLexer ( code ) ;
176194 const staticExports = exportSpecifiers . map ( ( { n : name } ) => name ) ;
195+ const isServerFirstRoute = staticExports . some (
196+ ( staticExport ) => staticExport === "ServerComponent" ,
197+ ) ;
177198 return {
178199 staticExports,
179- isServerFirstRoute : staticExports . some (
180- ( staticExport ) => staticExport === "ServerComponent" ,
181- ) ,
200+ isServerFirstRoute,
201+ hasClientExports : isServerFirstRoute
202+ ? staticExports . some ( isClientNonComponentExport )
203+ : staticExports . some ( isClientRouteExport ) ,
182204 } ;
183205}
184206
0 commit comments