From 90342d34f2f45a0236cef6bcdd96fb91d8a9032e Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 29 Mar 2023 19:53:28 +0800 Subject: [PATCH 1/6] fix(ssr): show ssr module loader error stack --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 466039d82b2ae2..67922af0cfd310 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -212,7 +212,8 @@ async function instantiateModule( server.config.logger.error( colors.red( `Error when evaluating SSR module ${url}:` + - (e.importee ? ` failed to import "${e.importee}"\n` : '\n'), + (e.importee ? ` failed to import "${e.importee}"` : '') + + `\n|- ${e.stack}\n`, ), { timestamp: true, From a17cf21c88245bc5f034c5ab3472ff7ccfa47cfd Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 30 Mar 2023 01:08:26 +0800 Subject: [PATCH 2/6] fix: ssrLoadModule importee --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 67922af0cfd310..706aada29baa9a 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -147,7 +147,10 @@ async function instantiateModule( context, urlStack, fixStacktrace, - ) + ).catch((err) => { + err.importee = dep + throw err + }) if (pendingDeps.length === 1) { pendingImports.delete(url) } else { @@ -222,7 +225,6 @@ async function instantiateModule( }, ) - delete e.importee throw e } From 22d8596aa38fdbac017992ac75b598cbef9f1544 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 30 Mar 2023 16:26:52 +0800 Subject: [PATCH 3/6] refactor: catch error in ssrImport --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 66 +++++++++---------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 706aada29baa9a..daa6adcdb21bed 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -131,35 +131,38 @@ async function instantiateModule( const pendingDeps: string[] = [] const ssrImport = async (dep: string) => { - if (dep[0] !== '.' && dep[0] !== '/') { - return nodeImport(dep, mod.file!, resolveOptions) - } - // convert to rollup URL because `pendingImports`, `moduleGraph.urlToModuleMap` requires that - dep = unwrapId(dep) - if (!isCircular(dep) && !pendingImports.get(dep)?.some(isCircular)) { - pendingDeps.push(dep) - if (pendingDeps.length === 1) { - pendingImports.set(url, pendingDeps) + try { + if (dep[0] !== '.' && dep[0] !== '/') { + return await nodeImport(dep, mod.file!, resolveOptions) } - const mod = await ssrLoadModule( - dep, - server, - context, - urlStack, - fixStacktrace, - ).catch((err) => { - err.importee = dep - throw err - }) - if (pendingDeps.length === 1) { - pendingImports.delete(url) - } else { - pendingDeps.splice(pendingDeps.indexOf(dep), 1) + // convert to rollup URL because `pendingImports`, `moduleGraph.urlToModuleMap` requires that + dep = unwrapId(dep) + if (!isCircular(dep) && !pendingImports.get(dep)?.some(isCircular)) { + pendingDeps.push(dep) + if (pendingDeps.length === 1) { + pendingImports.set(url, pendingDeps) + } + const mod = await ssrLoadModule( + dep, + server, + context, + urlStack, + fixStacktrace, + ) + if (pendingDeps.length === 1) { + pendingImports.delete(url) + } else { + pendingDeps.splice(pendingDeps.indexOf(dep), 1) + } + // return local module to avoid race condition #5470 + return mod } - // return local module to avoid race condition #5470 - return mod + return moduleGraph.urlToModuleMap.get(dep)?.ssrModule + } catch (err) { + // tell external error handler which mod was imported with error + err.importee = dep + throw err } - return moduleGraph.urlToModuleMap.get(dep)?.ssrModule } const ssrDynamicImport = (dep: string) => { @@ -265,15 +268,8 @@ async function nodeImport( } } - try { - const mod = await dynamicImport(url) - return proxyESM(mod) - } catch (err) { - // tell external error handler which mod was imported with error - err.importee = id - - throw err - } + const mod = await dynamicImport(url) + return proxyESM(mod) } // rollup-style default import interop for cjs From 59ff7ed97fba7de48afe8c9c58366f8c42312754 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 30 Mar 2023 19:38:53 +0800 Subject: [PATCH 4/6] feat: add a counter to mark ssr load err imported times --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index daa6adcdb21bed..eaa30a16b7a31f 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -160,7 +160,9 @@ async function instantiateModule( return moduleGraph.urlToModuleMap.get(dep)?.ssrModule } catch (err) { // tell external error handler which mod was imported with error + // add a counter to infer importer count, once counter = 0, remove the importee prop err.importee = dep + err.importerCount = (err.importerCount || 0) + 1 throw err } } @@ -228,6 +230,13 @@ async function instantiateModule( }, ) + e.importerCount-- + + if (!e.importerCount) { + delete e.importee + delete e.importerCount + } + throw e } From 11dd3674f8afe461f2725bef183eb3595c466f17 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 31 Mar 2023 11:51:56 +0800 Subject: [PATCH 5/6] feat: use WeakMap to store importee --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index eaa30a16b7a31f..664ab2bd115451 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -28,6 +28,7 @@ type SSRModule = Record const pendingModules = new Map>() const pendingImports = new Map() +const importErrors = new WeakMap() export async function ssrLoadModule( url: string, @@ -159,10 +160,15 @@ async function instantiateModule( } return moduleGraph.urlToModuleMap.get(dep)?.ssrModule } catch (err) { + let errorData = importErrors.get(err) // tell external error handler which mod was imported with error - // add a counter to infer importer count, once counter = 0, remove the importee prop - err.importee = dep - err.importerCount = (err.importerCount || 0) + 1 + if (errorData) { + errorData.importee = dep + } else { + errorData = { importee: dep } + } + importErrors.set(err, errorData) + throw err } } @@ -212,6 +218,7 @@ async function instantiateModule( ) } catch (e) { mod.ssrError = e + const errorData = importErrors.get(e) if (e.stack && fixStacktrace) { ssrFixStacktrace(e, moduleGraph) @@ -220,7 +227,9 @@ async function instantiateModule( server.config.logger.error( colors.red( `Error when evaluating SSR module ${url}:` + - (e.importee ? ` failed to import "${e.importee}"` : '') + + (errorData?.importee + ? ` failed to import "${errorData.importee}"` + : '') + `\n|- ${e.stack}\n`, ), { @@ -230,13 +239,6 @@ async function instantiateModule( }, ) - e.importerCount-- - - if (!e.importerCount) { - delete e.importee - delete e.importerCount - } - throw e } From b3f45d08ff475c4549e5d770c87d5d9b0027c53b Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 31 Mar 2023 20:33:41 +0800 Subject: [PATCH 6/6] refactor: always override importee --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 664ab2bd115451..cd234876a748e6 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -160,14 +160,8 @@ async function instantiateModule( } return moduleGraph.urlToModuleMap.get(dep)?.ssrModule } catch (err) { - let errorData = importErrors.get(err) // tell external error handler which mod was imported with error - if (errorData) { - errorData.importee = dep - } else { - errorData = { importee: dep } - } - importErrors.set(err, errorData) + importErrors.set(err, { importee: dep }) throw err }