@@ -226,6 +226,12 @@ async function instantiateModule(
226
226
return Object . freeze ( ssrModule )
227
227
}
228
228
229
+ // `nodeImport` may run in parallel on multiple `ssrLoadModule` calls.
230
+ // We keep track of the current importing count so that the first import
231
+ // would `hookNodeResolve`, and the last import would `unhookNodeResolve`.
232
+ let importingCount = 0
233
+ let unhookNodeResolve : ReturnType < typeof hookNodeResolve > | undefined
234
+
229
235
// In node@12+ we can use dynamic import to load CJS and ESM
230
236
async function nodeImport (
231
237
id : string ,
@@ -250,34 +256,36 @@ async function nodeImport(
250
256
return resolved . id
251
257
}
252
258
253
- // When an ESM module imports an ESM dependency, this hook is *not* used.
254
- const unhookNodeResolve = hookNodeResolve (
255
- ( nodeResolve ) => ( id , parent , isMain , options ) => {
256
- // Use the Vite resolver only for bare imports while skipping
257
- // any absolute paths, built-in modules and binary modules.
258
- if (
259
- ! bareImportRE . test ( id ) ||
260
- path . isAbsolute ( id ) ||
261
- isBuiltin ( id ) ||
262
- id . endsWith ( '.node' )
263
- ) {
264
- return nodeResolve ( id , parent , isMain , options )
265
- }
266
- if ( parent ) {
267
- let resolved = viteResolve ( id , parent . id )
268
- if ( resolved ) {
269
- // hookNodeResolve must use platform-specific path.normalize
270
- // to be compatible with dynamicImport (#6080)
271
- resolved = path . normalize ( resolved )
259
+ if ( importingCount === 0 ) {
260
+ // When an ESM module imports an ESM dependency, this hook is *not* used.
261
+ unhookNodeResolve = hookNodeResolve (
262
+ ( nodeResolve ) => ( id , parent , isMain , options ) => {
263
+ // Use the Vite resolver only for bare imports while skipping
264
+ // any absolute paths, built-in modules and binary modules.
265
+ if (
266
+ ! bareImportRE . test ( id ) ||
267
+ path . isAbsolute ( id ) ||
268
+ isBuiltin ( id ) ||
269
+ id . endsWith ( '.node' )
270
+ ) {
271
+ return nodeResolve ( id , parent , isMain , options )
272
272
}
273
- return resolved
273
+ if ( parent ) {
274
+ let resolved = viteResolve ( id , parent . id )
275
+ if ( resolved ) {
276
+ // hookNodeResolve must use platform-specific path.normalize
277
+ // to be compatible with dynamicImport (#6080)
278
+ resolved = path . normalize ( resolved )
279
+ }
280
+ return resolved
281
+ }
282
+ // Importing a CJS module from an ESM module. In this case, the import
283
+ // specifier is already an absolute path, so this is a no-op.
284
+ // Options like `resolve.dedupe` and `mode` are not respected.
285
+ return id
274
286
}
275
- // Importing a CJS module from an ESM module. In this case, the import
276
- // specifier is already an absolute path, so this is a no-op.
277
- // Options like `resolve.dedupe` and `mode` are not respected.
278
- return id
279
- }
280
- )
287
+ )
288
+ }
281
289
282
290
let url : string
283
291
if ( id . startsWith ( 'node:' ) || isBuiltin ( id ) ) {
@@ -299,10 +307,14 @@ async function nodeImport(
299
307
}
300
308
301
309
try {
310
+ importingCount ++
302
311
const mod = await dynamicImport ( url )
303
312
return proxyESM ( mod )
304
313
} finally {
305
- unhookNodeResolve ( )
314
+ importingCount --
315
+ if ( importingCount === 0 ) {
316
+ unhookNodeResolve ?.( )
317
+ }
306
318
}
307
319
}
308
320
0 commit comments