Skip to content

Commit

Permalink
feat(ssr)!: remove dedupe and mode support for CJS (#11101)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Nov 28, 2022
1 parent 2a4ffb7 commit 3090564
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 168 deletions.
2 changes: 0 additions & 2 deletions packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { modulePreloadPolyfillPlugin } from './modulePreloadPolyfill'
import { webWorkerPlugin } from './worker'
import { preAliasPlugin } from './preAlias'
import { definePlugin } from './define'
import { ssrRequireHookPlugin } from './ssrRequireHook'
import { workerImportMetaUrlPlugin } from './workerImportMetaUrl'
import { assetImportMetaUrlPlugin } from './assetImportMetaUrl'
import { ensureWatchPlugin } from './ensureWatch'
Expand Down Expand Up @@ -88,7 +87,6 @@ export async function resolvePlugins(
wasmFallbackPlugin(),
definePlugin(config),
cssPostPlugin(config),
isBuild && config.build.ssr ? ssrRequireHookPlugin(config) : null,
isBuild && buildHtmlPlugin(config),
workerImportMetaUrlPlugin(config),
assetImportMetaUrlPlugin(config),
Expand Down
3 changes: 0 additions & 3 deletions packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ export interface InternalResolveOptions extends Required<ResolveOptions> {
// Resolve using esbuild deps optimization
getDepsOptimizer?: (ssr: boolean) => DepsOptimizer | undefined
shouldExternalize?: (id: string) => boolean | undefined
// Check this resolve is called from `hookNodeResolve` in SSR
isHookNodeResolve?: boolean
}

export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
Expand Down Expand Up @@ -689,7 +687,6 @@ export function tryNodeResolve(
// if import can't be found, check if it's an optional peer dep.
// if so, we can resolve to a special id that errors only when imported.
if (
!options.isHookNodeResolve &&
basedir !== root && // root has no peer dep
!isBuiltin(nestedPath) &&
!nestedPath.includes('\0') &&
Expand Down
90 changes: 0 additions & 90 deletions packages/vite/src/node/plugins/ssrRequireHook.ts

This file was deleted.

87 changes: 14 additions & 73 deletions packages/vite/src/node/ssr/ssrModuleLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import path from 'node:path'
import { pathToFileURL } from 'node:url'
import type { ViteDevServer } from '../server'
import {
bareImportRE,
dynamicImport,
isBuiltin,
unwrapId,
Expand All @@ -11,7 +10,6 @@ import {
import { transformRequest } from '../server/transformRequest'
import type { InternalResolveOptions } from '../plugins/resolve'
import { tryNodeResolve } from '../plugins/resolve'
import { hookNodeResolve } from '../plugins/ssrRequireHook'
import {
ssrDynamicImportKey,
ssrExportAllKey,
Expand Down Expand Up @@ -114,21 +112,16 @@ async function instantiateModule(
root
} = server.config

// The `extensions` and `mainFields` options are used to ensure that
// CommonJS modules are preferred. We want to avoid ESM->ESM imports
// whenever possible, because `hookNodeResolve` can't intercept them.
const resolveOptions: InternalResolveOptions = {
mainFields: ['main'],
browserField: true,
conditions: [],
extensions: ['.js', '.cjs', '.json'],
dedupe,
preserveSymlinks,
isBuild: true,
isBuild: false,
isProduction,
isRequire: true,
root,
isHookNodeResolve: true
root
}

// Since dynamic imports can happen in parallel, we need to
Expand Down Expand Up @@ -227,96 +220,44 @@ async function instantiateModule(
return Object.freeze(ssrModule)
}

// `nodeImport` may run in parallel on multiple `ssrLoadModule` calls.
// We keep track of the current importing count so that the first import
// would `hookNodeResolve`, and the last import would `unhookNodeResolve`.
let importingCount = 0
let unhookNodeResolve: ReturnType<typeof hookNodeResolve> | undefined

// In node@12+ we can use dynamic import to load CJS and ESM
async function nodeImport(
id: string,
importer: string,
resolveOptions: InternalResolveOptions
) {
// Node's module resolution is hi-jacked so Vite can ensure the
// configured `resolve.dedupe` and `mode` options are respected.
const viteResolve = (
id: string,
importer: string,
options = resolveOptions
) => {
const resolved = tryNodeResolve(id, importer, options, false)
if (!resolved) {
const err: any = new Error(
`Cannot find module '${id}' imported from '${importer}'`
)
err.code = 'ERR_MODULE_NOT_FOUND'
throw err
}
return resolved.id
}

if (importingCount === 0) {
// When an ESM module imports an ESM dependency, this hook is *not* used.
unhookNodeResolve = hookNodeResolve(
(nodeResolve) => (id, parent, isMain, options) => {
// Use the Vite resolver only for bare imports while skipping
// any absolute paths, built-in modules and binary modules.
if (
!bareImportRE.test(id) ||
path.isAbsolute(id) ||
isBuiltin(id) ||
id.endsWith('.node')
) {
return nodeResolve(id, parent, isMain, options)
}
if (parent) {
let resolved = viteResolve(id, parent.id)
if (resolved) {
// hookNodeResolve must use platform-specific path.normalize
// to be compatible with dynamicImport (#6080)
resolved = path.normalize(resolved)
}
return resolved
}
// Importing a CJS module from an ESM module. In this case, the import
// specifier is already an absolute path, so this is a no-op.
// Options like `resolve.dedupe` and `mode` are not respected.
return id
}
)
}

let url: string
if (id.startsWith('node:') || isBuiltin(id)) {
url = id
} else {
url = viteResolve(
const resolved = tryNodeResolve(
id,
importer,
// Non-external modules can import ESM-only modules, but only outside
// of test runs, because we use Node `require` in Jest to avoid segfault.
// @ts-expect-error
typeof jest === 'undefined'
? { ...resolveOptions, tryEsmOnly: true }
: resolveOptions
: resolveOptions,
false
)
if (!resolved) {
const err: any = new Error(
`Cannot find module '${id}' imported from '${importer}'`
)
err.code = 'ERR_MODULE_NOT_FOUND'
throw err
}
url = resolved.id
if (usingDynamicImport) {
url = pathToFileURL(url).toString()
}
}

try {
importingCount++
const mod = await dynamicImport(url)
return proxyESM(mod)
} finally {
importingCount--
if (importingCount === 0) {
unhookNodeResolve?.()
}
}
} catch {}
}

// rollup-style default import interop for cjs
Expand Down

0 comments on commit 3090564

Please sign in to comment.