Skip to content

Commit 1663f5c

Browse files
authoredJan 12, 2024
fix(vitest): add inlined deps to ssr.noExternal so they are added to the module graph (#4945)
1 parent 9ae9dac commit 1663f5c

File tree

6 files changed

+153
-15
lines changed

6 files changed

+153
-15
lines changed
 

‎packages/vite-node/src/server.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ export class ViteNodeServer {
6565
}
6666
else if (options.deps.inline !== true) {
6767
options.deps.inline ??= []
68-
options.deps.inline.push(...toArray(ssrOptions.noExternal))
68+
const inline = options.deps.inline
69+
options.deps.inline.push(...toArray(ssrOptions.noExternal).filter(dep => !inline.includes(dep)))
6970
}
7071
}
7172
if (process.env.VITE_NODE_DEBUG_DUMP) {

‎packages/vitest/src/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface UserWorkspaceConfig extends ViteUserConfig {
88
// will import vitest declare test in module 'vite'
99
export { configDefaults, defaultInclude, defaultExclude, coverageConfigDefaults } from './defaults'
1010
export { mergeConfig } from 'vite'
11+
export { extraInlineDeps } from './constants'
1112

1213
export type { ConfigEnv, ViteUserConfig as UserConfig }
1314
export type UserConfigFnObject = (env: ConfigEnv) => ViteUserConfig

‎packages/vitest/src/constants.ts

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ export const EXIT_CODE_RESTART = 43
66

77
export const API_PATH = '/__vitest_api__'
88

9+
export const extraInlineDeps = [
10+
/^(?!.*(?:node_modules)).*\.mjs$/,
11+
/^(?!.*(?:node_modules)).*\.cjs\.js$/,
12+
// Vite client
13+
/vite\w*\/dist\/client\/env.mjs/,
14+
// Nuxt
15+
'@nuxt/test-utils',
16+
]
17+
918
export const CONFIG_NAMES = [
1019
'vitest.config',
1120
'vite.config',

‎packages/vitest/src/node/config.ts

+1-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { normalize, relative, resolve } from 'pathe'
33
import c from 'picocolors'
44
import type { ResolvedConfig as ResolvedViteConfig } from 'vite'
55
import type { ApiConfig, ResolvedConfig, UserConfig, VitestRunMode } from '../types'
6-
import { defaultBrowserPort, defaultPort } from '../constants'
6+
import { defaultBrowserPort, defaultPort, extraInlineDeps } from '../constants'
77
import { benchmarkConfigDefaults, configDefaults } from '../defaults'
88
import { isCI, stdProvider, toArray } from '../utils'
99
import type { BuiltinPool } from '../types/pool-options'
@@ -13,15 +13,6 @@ import { RandomSequencer } from './sequencers/RandomSequencer'
1313
import type { BenchmarkBuiltinReporters } from './reporters'
1414
import { builtinPools } from './pool'
1515

16-
const extraInlineDeps = [
17-
/^(?!.*(?:node_modules)).*\.mjs$/,
18-
/^(?!.*(?:node_modules)).*\.cjs\.js$/,
19-
// Vite client
20-
/vite\w*\/dist\/client\/env.mjs/,
21-
// Nuxt
22-
'@nuxt/test-utils',
23-
]
24-
2516
function resolvePath(path: string, root: string) {
2617
return normalize(
2718
resolveModule(path, { paths: [root] })

‎packages/vitest/src/node/plugins/index.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite'
22
import { relative } from 'pathe'
33
import { configDefaults } from '../../defaults'
44
import type { ResolvedConfig, UserConfig } from '../../types'
5-
import { deepMerge, notNullish, removeUndefinedValues } from '../../utils'
5+
import { deepMerge, notNullish, removeUndefinedValues, toArray } from '../../utils'
66
import { ensurePackageInstalled } from '../pkg'
77
import { resolveApiServerConfig } from '../config'
88
import { Vitest } from '../core'
@@ -103,6 +103,25 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t
103103
},
104104
}
105105

106+
// we want inline dependencies to be resolved by analyser plugin so module graph is populated correctly
107+
if (viteConfig.ssr?.noExternal !== true) {
108+
const inline = testConfig.server?.deps?.inline
109+
if (inline === true) {
110+
config.ssr = { noExternal: true }
111+
}
112+
else {
113+
const noExternal = viteConfig.ssr?.noExternal
114+
const noExternalArray = typeof noExternal !== 'undefined' ? toArray(noExternal) : undefined
115+
// filter the same packages
116+
const uniqueInline = inline && noExternalArray
117+
? inline.filter(dep => !noExternalArray.includes(dep))
118+
: inline
119+
config.ssr = {
120+
noExternal: uniqueInline,
121+
}
122+
}
123+
}
124+
106125
// chokidar fsevents is unstable on macos when emitting "ready" event
107126
if (process.platform === 'darwin' && process.env.VITE_TEST_WATCHER_DEBUG) {
108127
config.server!.watch!.useFsEvents = false

‎test/config/test/resolution.test.ts

+120-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import type { UserConfig } from 'vitest'
2+
import type { UserConfig as ViteUserConfig } from 'vite'
23
import { describe, expect, it } from 'vitest'
34
import { createVitest } from 'vitest/node'
5+
import { extraInlineDeps } from 'vitest/config'
46

5-
async function config(cliOptions: UserConfig, configValue: UserConfig = {}) {
6-
const vitest = await createVitest('test', { ...cliOptions, watch: false }, { test: configValue })
7-
return vitest.config
7+
async function vitest(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}) {
8+
const vitest = await createVitest('test', { ...cliOptions, watch: false }, { ...viteConfig, test: configValue as any })
9+
return vitest
10+
}
11+
12+
async function config(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}) {
13+
const v = await vitest(cliOptions, configValue, viteConfig)
14+
return v.config
815
}
916

1017
describe('correctly defines isolated flags', async () => {
@@ -102,3 +109,113 @@ describe('correctly defines isolated flags', async () => {
102109
expect(c.isolate).toBe(true)
103110
})
104111
})
112+
113+
describe('correctly defines inline and noExternal flags', async () => {
114+
it('both are true if inline is true', async () => {
115+
const v = await vitest({}, {
116+
server: {
117+
deps: {
118+
inline: true,
119+
},
120+
},
121+
})
122+
expect(v.vitenode.options.deps?.inline).toBe(true)
123+
expect(v.vitenode.server.config.ssr.noExternal).toBe(true)
124+
})
125+
126+
it('both are true if noExternal is true', async () => {
127+
const v = await vitest({}, {}, {
128+
ssr: {
129+
noExternal: true,
130+
},
131+
})
132+
expect(v.vitenode.options.deps?.inline).toBe(true)
133+
expect(v.vitenode.server.config.ssr.noExternal).toBe(true)
134+
})
135+
136+
it('inline are added to noExternal', async () => {
137+
const regexp1 = /dep1/
138+
const regexp2 = /dep2/
139+
140+
const v = await vitest({}, {
141+
server: {
142+
deps: {
143+
inline: ['dep1', 'dep2', regexp1, regexp2],
144+
},
145+
},
146+
})
147+
148+
expect(v.vitenode.options.deps?.inline).toEqual([
149+
'dep1',
150+
'dep2',
151+
regexp1,
152+
regexp2,
153+
...extraInlineDeps,
154+
])
155+
expect(v.server.config.ssr.noExternal).toEqual([
156+
'dep1',
157+
'dep2',
158+
regexp1,
159+
regexp2,
160+
...extraInlineDeps,
161+
])
162+
})
163+
164+
it('noExternal are added to inline', async () => {
165+
const regexp1 = /dep1/
166+
const regexp2 = /dep2/
167+
168+
const v = await vitest({}, {}, {
169+
ssr: {
170+
noExternal: ['dep1', 'dep2', regexp1, regexp2],
171+
},
172+
})
173+
174+
expect(v.vitenode.options.deps?.inline).toEqual([
175+
...extraInlineDeps,
176+
'dep1',
177+
'dep2',
178+
regexp1,
179+
regexp2,
180+
])
181+
expect(v.server.config.ssr.noExternal).toEqual([
182+
'dep1',
183+
'dep2',
184+
regexp1,
185+
regexp2,
186+
])
187+
})
188+
189+
it('noExternal and inline don\'t have duplicates', async () => {
190+
const regexp1 = /dep1/
191+
const regexp2 = /dep2/
192+
193+
const v = await vitest({}, {
194+
server: {
195+
deps: {
196+
inline: ['dep2', regexp1, 'dep3'],
197+
},
198+
},
199+
}, {
200+
ssr: {
201+
noExternal: ['dep1', 'dep2', regexp1, regexp2],
202+
},
203+
})
204+
205+
expect(v.vitenode.options.deps?.inline).toEqual([
206+
'dep2',
207+
regexp1,
208+
'dep3',
209+
...extraInlineDeps,
210+
'dep1',
211+
regexp2,
212+
])
213+
expect(v.server.config.ssr.noExternal).toEqual([
214+
'dep1',
215+
'dep2',
216+
regexp1,
217+
regexp2,
218+
'dep3',
219+
])
220+
})
221+
})

0 commit comments

Comments
 (0)
Please sign in to comment.