Skip to content

Commit

Permalink
feat(vite-node): respect ssr field, allow inlining everything (#1434)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Jun 5, 2022
1 parent 692ad34 commit fd57b0e
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 17 deletions.
4 changes: 3 additions & 1 deletion docs/config/index.md
Expand Up @@ -82,11 +82,13 @@ Externalize means that Vite will bypass the package to native Node. Externalized

#### deps.inline

- **Type:** `(string | RegExp)[]`
- **Type:** `(string | RegExp)[] | true`
- **Default:** `[]`

Vite will process inlined modules. This could be helpful to handle packages that ship `.js` in ESM format (that Node can't handle).

If `true`, every dependency will be inlined. All dependencies, specified in [`ssr.noExternal`](https://vitejs.dev/guide/ssr.html#ssr-externals) will be inlined by default.

#### deps.fallbackCJS

- **Type** `boolean`
Expand Down
22 changes: 14 additions & 8 deletions packages/vite-node/src/cli.ts
Expand Up @@ -90,15 +90,19 @@ async function run(files: string[], options: CliOptions = {}) {
}

function parseServerOptions(serverOptions: ViteNodeServerOptionsCLI): ViteNodeServerOptions {
const inlineOptions = serverOptions.deps?.inline === true ? true : toArray(serverOptions.deps?.inline)

return {
...serverOptions,
deps: {
...serverOptions.deps,
inline: toArray(serverOptions.deps?.inline).map((dep) => {
return dep.startsWith('/') && dep.endsWith('/')
? new RegExp(dep)
: dep
}),
inline: inlineOptions !== true
? inlineOptions.map((dep) => {
return dep.startsWith('/') && dep.endsWith('/')
? new RegExp(dep)
: dep
})
: true,
external: toArray(serverOptions.deps?.external).map((dep) => {
return dep.startsWith('/') && dep.endsWith('/')
? new RegExp(dep)
Expand All @@ -121,9 +125,11 @@ type ComputeViteNodeServerOptionsCLI<T extends Record<string, any>> = {
? string | string[]
: T[K] extends Optional<(string | RegExp)[]>
? string | string[]
: T[K] extends Optional<Record<string, any>>
? ComputeViteNodeServerOptionsCLI<T[K]>
: T[K]
: T[K] extends Optional<(string | RegExp)[] | true>
? string | string[] | true
: T[K] extends Optional<Record<string, any>>
? ComputeViteNodeServerOptionsCLI<T[K]>
: T[K]
}

export type ViteNodeServerOptionsCLI = ComputeViteNodeServerOptionsCLI<ViteNodeServerOptions>
6 changes: 4 additions & 2 deletions packages/vite-node/src/externalize.ts
Expand Up @@ -85,9 +85,11 @@ async function _shouldExternalize(
return false
}

function matchExternalizePattern(id: string, patterns?: (string | RegExp)[]) {
if (!patterns)
function matchExternalizePattern(id: string, patterns?: (string | RegExp)[] | true) {
if (patterns == null)
return false
if (patterns === true)
return true
for (const ex of patterns) {
if (typeof ex === 'string') {
if (id.includes(`/node_modules/${ex}/`))
Expand Down
24 changes: 22 additions & 2 deletions packages/vite-node/src/server.ts
Expand Up @@ -3,7 +3,7 @@ import type { TransformResult, ViteDevServer } from 'vite'
import createDebug from 'debug'
import type { FetchResult, RawSourceMap, ViteNodeResolveId, ViteNodeServerOptions } from './types'
import { shouldExternalize } from './externalize'
import { toFilePath, withInlineSourcemap } from './utils'
import { toArray, toFilePath, withInlineSourcemap } from './utils'

export * from './externalize'

Expand All @@ -24,7 +24,27 @@ export class ViteNodeServer {
constructor(
public server: ViteDevServer,
public options: ViteNodeServerOptions = {},
) {}
) {
// @ts-expect-error ssr is not typed
const ssrOptions = server.config.ssr
if (ssrOptions) {
options.deps ??= {}

// we don't externalize ssr, because it has different semantics in Vite
// if (ssrOptions.external) {
// options.deps.external ??= []
// options.deps.external.push(...ssrOptions.external)
// }

if (ssrOptions.noExternal === true) {
options.deps.inline ??= true
}
else if (options.deps.inline !== true) {
options.deps.inline ??= []
options.deps.inline.push(...toArray(ssrOptions.noExternal))
}
}
}

shouldExternalize(id: string) {
return shouldExternalize(id, this.options.deps)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite-node/src/types.ts
Expand Up @@ -5,7 +5,7 @@ export type Arrayable<T> = T | Array<T>

export interface DepsHandlingOptions {
external?: (string | RegExp)[]
inline?: (string | RegExp)[]
inline?: (string | RegExp)[] | true
/**
* Try to guess the CJS version of a package when it's invalid ESM
* @default false
Expand Down
14 changes: 12 additions & 2 deletions packages/vitest/src/node/config.ts
Expand Up @@ -93,8 +93,18 @@ export function resolveConfig(
resolved.deps = resolved.deps || {}
// vitenode will try to import such file with native node,
// but then our mocker will not work properly
resolved.deps.inline ??= []
resolved.deps.inline.push(...extraInlineDeps)
if (resolved.deps.inline !== true) {
// @ts-expect-error ssr is not typed
const ssrOptions = viteConfig.ssr || {}

if (ssrOptions.noExternal === true && resolved.deps.inline == null) {
resolved.deps.inline = true
}
else {
resolved.deps.inline ??= []
resolved.deps.inline.push(...extraInlineDeps)
}
}

resolved.testNamePattern = resolved.testNamePattern
? resolved.testNamePattern instanceof RegExp
Expand Down
4 changes: 3 additions & 1 deletion packages/vitest/src/types/config.ts
Expand Up @@ -59,8 +59,10 @@ export interface InlineConfig {
* Vite will process inlined modules.
*
* This could be helpful to handle packages that ship `.js` in ESM format (that Node can't handle).
*
* If `true`, every dependency will be inlined
*/
inline?: (string | RegExp)[]
inline?: (string | RegExp)[] | true

/**
* Interpret CJS module's default as named exports
Expand Down

0 comments on commit fd57b0e

Please sign in to comment.