From 4d4d290a13fd3921ac77e966d89cafa71aae852c Mon Sep 17 00:00:00 2001 From: patak-dev Date: Sun, 24 Jul 2022 23:24:18 +0200 Subject: [PATCH 1/3] fix: externalize explicitly configured linked packages --- packages/vite/src/node/plugins/resolve.ts | 9 +++++---- packages/vite/src/node/ssr/ssrExternal.ts | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index d82e1dc6bc63ac..5363e6a4c246eb 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -556,7 +556,8 @@ export function tryNodeResolve( targetWeb: boolean, depsOptimizer?: DepsOptimizer, ssr?: boolean, - externalize?: boolean + externalize?: boolean, + allowLinkedExternal: boolean = true ): PartialResolvedId | undefined { const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options @@ -657,8 +658,8 @@ export function tryNodeResolve( return resolved } // dont external symlink packages - if (!resolved.id.includes('node_modules')) { - return + if (!allowLinkedExternal && !resolved.id.includes('node_modules')) { + return resolved } const resolvedExt = path.extname(resolved.id) let resolvedId = id @@ -666,7 +667,7 @@ export function tryNodeResolve( // check ext before externalizing - only externalize // extension-less imports and explicit .js imports if (resolvedExt && !resolved.id.match(/(.js|.mjs|.cjs)$/)) { - return + return resolved } if (!pkg?.data.exports && path.extname(id) !== resolvedExt) { resolvedId += resolvedExt diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index 74423748565acf..dcdf48d29c6596 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -138,7 +138,7 @@ export function createIsConfiguredAsSsrExternal( // Return undefined here to avoid short-circuiting the isExternalizable check, // that will filter this id out if it is not externalizable (e.g. a CSS file) // We return here to make ssr.external take precedence over noExternal - return undefined + return true } if (typeof noExternal === 'boolean') { return !noExternal @@ -167,7 +167,7 @@ function createIsSsrExternal( isBuild: true } - const isExternalizable = (id: string) => { + const isExternalizable = (id: string, configuredAsExternal?: boolean) => { if (!bareImportRE.test(id) || id.includes('\0')) { return false } @@ -178,8 +178,13 @@ function createIsSsrExternal( ssr?.target === 'webworker', undefined, true, - true // try to externalize, will return undefined if not possible - ) + // try to externalize, will return undefined or an object without + // a external flag if it isn't externalizable + true, + // Allow linked packages to be externalized if they are explicitly + // configured as external + !!configuredAsExternal + )?.external } return (id: string) => { @@ -188,8 +193,14 @@ function createIsSsrExternal( } let external = false if (!id.startsWith('.') && !path.isAbsolute(id)) { - external = - isBuiltin(id) || (isConfiguredAsExternal(id) ?? isExternalizable(id)) + if (isBuiltin(id)) { + external = true + } else { + const configuredAsExternal = isConfiguredAsExternal(id) + if (configuredAsExternal !== false) { + external = isExternalizable(id, configuredAsExternal) + } + } } processedIds.set(id, external) return external From 3e601256d5437504dd32890e6d3d568c747c55a1 Mon Sep 17 00:00:00 2001 From: patak-dev Date: Sun, 24 Jul 2022 23:42:18 +0200 Subject: [PATCH 2/3] chore: update --- packages/vite/src/node/ssr/ssrExternal.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index dcdf48d29c6596..a1c62339c7cc27 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -120,10 +120,6 @@ export function createIsConfiguredAsSsrExternal( return (id: string) => { const { ssr } = config if (ssr) { - const pkgName = getNpmPackageName(id) - if (!pkgName) { - return undefined - } if ( // If this id is defined as external, force it as external // Note that individual package entries are allowed in ssr.external @@ -131,13 +127,15 @@ export function createIsConfiguredAsSsrExternal( ) { return true } + const pkgName = getNpmPackageName(id) + if (!pkgName) { + return undefined + } if ( - // A package name in ssr.external externalizes every entry + // A package name in ssr.external externalizes every + // externalizable package entry ssr.external?.includes(pkgName) ) { - // Return undefined here to avoid short-circuiting the isExternalizable check, - // that will filter this id out if it is not externalizable (e.g. a CSS file) - // We return here to make ssr.external take precedence over noExternal return true } if (typeof noExternal === 'boolean') { From 511169c1ab65fa56d390e9c367b4740d65117bad Mon Sep 17 00:00:00 2001 From: patak-dev Date: Mon, 25 Jul 2022 06:46:50 +0200 Subject: [PATCH 3/3] chore: fix sveltekit regression --- packages/vite/src/node/ssr/ssrExternal.ts | 78 +++++++++++------------ 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index a1c62339c7cc27..5fa073ddc2d58a 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -107,14 +107,44 @@ export function shouldExternalizeForSSR( export function createIsConfiguredAsSsrExternal( config: ResolvedConfig -): (id: string) => boolean | undefined { - const { ssr } = config +): (id: string) => boolean { + const { ssr, root } = config const noExternal = ssr?.noExternal const noExternalFilter = noExternal !== 'undefined' && typeof noExternal !== 'boolean' && createFilter(undefined, noExternal, { resolve: false }) + const resolveOptions: InternalResolveOptions = { + root, + preserveSymlinks: config.resolve.preserveSymlinks, + isProduction: false, + isBuild: true + } + + const isExternalizable = ( + id: string, + configuredAsExternal?: boolean + ): boolean => { + if (!bareImportRE.test(id) || id.includes('\0')) { + return false + } + return !!tryNodeResolve( + id, + undefined, + resolveOptions, + ssr?.target === 'webworker', + undefined, + true, + // try to externalize, will return undefined or an object without + // a external flag if it isn't externalizable + true, + // Allow linked packages to be externalized if they are explicitly + // configured as external + !!configuredAsExternal + )?.external + } + // Returns true if it is configured as external, false if it is filtered // by noExternal and undefined if it isn't affected by the explicit config return (id: string) => { @@ -129,14 +159,14 @@ export function createIsConfiguredAsSsrExternal( } const pkgName = getNpmPackageName(id) if (!pkgName) { - return undefined + return isExternalizable(id) } if ( // A package name in ssr.external externalizes every // externalizable package entry ssr.external?.includes(pkgName) ) { - return true + return isExternalizable(id, true) } if (typeof noExternal === 'boolean') { return !noExternal @@ -145,7 +175,7 @@ export function createIsConfiguredAsSsrExternal( return false } } - return undefined + return isExternalizable(id) } } @@ -154,51 +184,15 @@ function createIsSsrExternal( ): (id: string) => boolean | undefined { const processedIds = new Map() - const { ssr, root } = config - const isConfiguredAsExternal = createIsConfiguredAsSsrExternal(config) - const resolveOptions: InternalResolveOptions = { - root, - preserveSymlinks: config.resolve.preserveSymlinks, - isProduction: false, - isBuild: true - } - - const isExternalizable = (id: string, configuredAsExternal?: boolean) => { - if (!bareImportRE.test(id) || id.includes('\0')) { - return false - } - return !!tryNodeResolve( - id, - undefined, - resolveOptions, - ssr?.target === 'webworker', - undefined, - true, - // try to externalize, will return undefined or an object without - // a external flag if it isn't externalizable - true, - // Allow linked packages to be externalized if they are explicitly - // configured as external - !!configuredAsExternal - )?.external - } - return (id: string) => { if (processedIds.has(id)) { return processedIds.get(id) } let external = false if (!id.startsWith('.') && !path.isAbsolute(id)) { - if (isBuiltin(id)) { - external = true - } else { - const configuredAsExternal = isConfiguredAsExternal(id) - if (configuredAsExternal !== false) { - external = isExternalizable(id, configuredAsExternal) - } - } + external = isBuiltin(id) || isConfiguredAsExternal(id) } processedIds.set(id, external) return external