Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vite-node): respect ssr field, allow inlining everything #1434

Merged
merged 6 commits into from Jun 5, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.

#### 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
sheremet-va marked this conversation as resolved.
Show resolved Hide resolved
}
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
6 changes: 4 additions & 2 deletions packages/vitest/src/node/config.ts
Expand Up @@ -93,8 +93,10 @@ 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) {
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