Skip to content

Commit c33e365

Browse files
authoredJul 25, 2022
fix: externalize explicitly configured linked packages (#9346)
1 parent ccb3449 commit c33e365

File tree

2 files changed

+46
-42
lines changed

2 files changed

+46
-42
lines changed
 

‎packages/vite/src/node/plugins/resolve.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ export function tryNodeResolve(
556556
targetWeb: boolean,
557557
depsOptimizer?: DepsOptimizer,
558558
ssr?: boolean,
559-
externalize?: boolean
559+
externalize?: boolean,
560+
allowLinkedExternal: boolean = true
560561
): PartialResolvedId | undefined {
561562
const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options
562563

@@ -657,16 +658,16 @@ export function tryNodeResolve(
657658
return resolved
658659
}
659660
// dont external symlink packages
660-
if (!resolved.id.includes('node_modules')) {
661-
return
661+
if (!allowLinkedExternal && !resolved.id.includes('node_modules')) {
662+
return resolved
662663
}
663664
const resolvedExt = path.extname(resolved.id)
664665
let resolvedId = id
665666
if (isDeepImport) {
666667
// check ext before externalizing - only externalize
667668
// extension-less imports and explicit .js imports
668669
if (resolvedExt && !resolved.id.match(/(.js|.mjs|.cjs)$/)) {
669-
return
670+
return resolved
670671
}
671672
if (!pkg?.data.exports && path.extname(id) !== resolvedExt) {
672673
resolvedId += resolvedExt

‎packages/vite/src/node/ssr/ssrExternal.ts

+41-38
Original file line numberDiff line numberDiff line change
@@ -107,38 +107,66 @@ export function shouldExternalizeForSSR(
107107

108108
export function createIsConfiguredAsSsrExternal(
109109
config: ResolvedConfig
110-
): (id: string) => boolean | undefined {
111-
const { ssr } = config
110+
): (id: string) => boolean {
111+
const { ssr, root } = config
112112
const noExternal = ssr?.noExternal
113113
const noExternalFilter =
114114
noExternal !== 'undefined' &&
115115
typeof noExternal !== 'boolean' &&
116116
createFilter(undefined, noExternal, { resolve: false })
117117

118+
const resolveOptions: InternalResolveOptions = {
119+
root,
120+
preserveSymlinks: config.resolve.preserveSymlinks,
121+
isProduction: false,
122+
isBuild: true
123+
}
124+
125+
const isExternalizable = (
126+
id: string,
127+
configuredAsExternal?: boolean
128+
): boolean => {
129+
if (!bareImportRE.test(id) || id.includes('\0')) {
130+
return false
131+
}
132+
return !!tryNodeResolve(
133+
id,
134+
undefined,
135+
resolveOptions,
136+
ssr?.target === 'webworker',
137+
undefined,
138+
true,
139+
// try to externalize, will return undefined or an object without
140+
// a external flag if it isn't externalizable
141+
true,
142+
// Allow linked packages to be externalized if they are explicitly
143+
// configured as external
144+
!!configuredAsExternal
145+
)?.external
146+
}
147+
118148
// Returns true if it is configured as external, false if it is filtered
119149
// by noExternal and undefined if it isn't affected by the explicit config
120150
return (id: string) => {
121151
const { ssr } = config
122152
if (ssr) {
123-
const pkgName = getNpmPackageName(id)
124-
if (!pkgName) {
125-
return undefined
126-
}
127153
if (
128154
// If this id is defined as external, force it as external
129155
// Note that individual package entries are allowed in ssr.external
130156
ssr.external?.includes(id)
131157
) {
132158
return true
133159
}
160+
const pkgName = getNpmPackageName(id)
161+
if (!pkgName) {
162+
return isExternalizable(id)
163+
}
134164
if (
135-
// A package name in ssr.external externalizes every entry
165+
// A package name in ssr.external externalizes every
166+
// externalizable package entry
136167
ssr.external?.includes(pkgName)
137168
) {
138-
// Return undefined here to avoid short-circuiting the isExternalizable check,
139-
// that will filter this id out if it is not externalizable (e.g. a CSS file)
140-
// We return here to make ssr.external take precedence over noExternal
141-
return undefined
169+
return isExternalizable(id, true)
142170
}
143171
if (typeof noExternal === 'boolean') {
144172
return !noExternal
@@ -147,7 +175,7 @@ export function createIsConfiguredAsSsrExternal(
147175
return false
148176
}
149177
}
150-
return undefined
178+
return isExternalizable(id)
151179
}
152180
}
153181

@@ -156,40 +184,15 @@ function createIsSsrExternal(
156184
): (id: string) => boolean | undefined {
157185
const processedIds = new Map<string, boolean | undefined>()
158186

159-
const { ssr, root } = config
160-
161187
const isConfiguredAsExternal = createIsConfiguredAsSsrExternal(config)
162188

163-
const resolveOptions: InternalResolveOptions = {
164-
root,
165-
preserveSymlinks: config.resolve.preserveSymlinks,
166-
isProduction: false,
167-
isBuild: true
168-
}
169-
170-
const isExternalizable = (id: string) => {
171-
if (!bareImportRE.test(id) || id.includes('\0')) {
172-
return false
173-
}
174-
return !!tryNodeResolve(
175-
id,
176-
undefined,
177-
resolveOptions,
178-
ssr?.target === 'webworker',
179-
undefined,
180-
true,
181-
true // try to externalize, will return undefined if not possible
182-
)
183-
}
184-
185189
return (id: string) => {
186190
if (processedIds.has(id)) {
187191
return processedIds.get(id)
188192
}
189193
let external = false
190194
if (!id.startsWith('.') && !path.isAbsolute(id)) {
191-
external =
192-
isBuiltin(id) || (isConfiguredAsExternal(id) ?? isExternalizable(id))
195+
external = isBuiltin(id) || isConfiguredAsExternal(id)
193196
}
194197
processedIds.set(id, external)
195198
return external

0 commit comments

Comments
 (0)
Please sign in to comment.