@@ -86,3 +86,45 @@ describe('indexHtml middleware — /@fs/ inline script proxy cache', () => {
8686 expect ( result ! . code ) . toContain ( 'module loaded' )
8787 } )
8888} )
89+
90+ describe ( 'indexHtml middleware — HMR timestamp injection with non-root base' , ( ) => {
91+ test ( 'entry script URL gets the lastHMRTimestamp query when base is not root' , async ( ) => {
92+ const root = path . resolve ( import . meta. dirname , 'fixtures/base-root' )
93+ const server = await createServer ( {
94+ configFile : false ,
95+ root,
96+ base : '/ui/' ,
97+ logLevel : 'error' ,
98+ server : {
99+ middlewareMode : true ,
100+ ws : false ,
101+ } ,
102+ optimizeDeps : {
103+ noDiscovery : true ,
104+ include : [ ] ,
105+ } ,
106+ } )
107+ onTestFinished ( ( ) => server . close ( ) )
108+
109+ // Register the entry in the module graph under the base-stripped URL
110+ // (as the transform middleware records it) and mark it HMR-updated.
111+ await server . environments . client . transformRequest ( '/src/main.ts' )
112+ const mod =
113+ server . environments . client . moduleGraph . urlToModuleMap . get ( '/src/main.ts' )
114+ expect (
115+ mod ,
116+ 'entry module should be registered under the base-stripped URL' ,
117+ ) . toBeTruthy ( )
118+ const timestamp = 1234567890
119+ mod ! . lastHMRTimestamp = timestamp
120+
121+ const html = `<!doctype html><html><body><script type="module" src="/src/main.ts"></script></body></html>`
122+ const transformed = await server . transformIndexHtml ( '/index.html' , html )
123+
124+ // Without stripping the base before the module graph lookup, the entry
125+ // stays a bare `/ui/src/main.ts` while the module's own references get
126+ // the timestamp — two different URLs for the same module, executing the
127+ // entry twice.
128+ expect ( transformed ) . toContain ( `src="/ui/src/main.ts?t=${ timestamp } "` )
129+ } )
130+ } )
0 commit comments