From f623ba37dbc517656a7ffb10bc1b3cb221a4bc72 Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Thu, 24 Jun 2021 21:06:14 +0800 Subject: [PATCH] fix(ssr): not importing browser exports, fix #3772 (#3933) --- packages/vite/src/node/config.ts | 7 ++++--- .../src/node/optimizer/esbuildDepPlugin.ts | 5 +++-- packages/vite/src/node/optimizer/index.ts | 5 +++-- .../src/node/optimizer/registerMissing.ts | 15 ++++++++----- packages/vite/src/node/plugins/resolve.ts | 21 ++++++++++++------- packages/vite/src/node/server/index.ts | 4 +++- packages/vite/src/node/ssr/ssrExternal.ts | 9 +++++++- 7 files changed, 44 insertions(+), 22 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 5ef64be1f33454..0f0e91651af9af 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -223,7 +223,8 @@ export type ResolvedConfig = Readonly< export type ResolveFn = ( id: string, importer?: string, - aliasOnly?: boolean + aliasOnly?: boolean, + ssr?: boolean ) => Promise export async function resolveConfig( @@ -347,7 +348,7 @@ export async function resolveConfig( const createResolver: ResolvedConfig['createResolver'] = (options) => { let aliasContainer: PluginContainer | undefined let resolverContainer: PluginContainer | undefined - return async (id, importer, aliasOnly) => { + return async (id, importer, aliasOnly, ssr) => { let container: PluginContainer if (aliasOnly) { container = @@ -377,7 +378,7 @@ export async function resolveConfig( ] })) } - return (await container.resolveId(id, importer))?.id + return (await container.resolveId(id, importer, undefined, ssr))?.id } } diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index fe12a55bd4b448..7459c3b21e613a 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -35,7 +35,8 @@ const externalTypes = [ export function esbuildDepPlugin( qualified: Record, exportsData: Record, - config: ResolvedConfig + config: ResolvedConfig, + ssr?: boolean ): Plugin { // default resolver which prefers ESM const _resolve = config.createResolver({ asSrc: false }) @@ -62,7 +63,7 @@ export function esbuildDepPlugin( _importer = importer in qualified ? qualified[importer] : importer } const resolver = kind.startsWith('require') ? _resolveRequire : _resolve - return resolver(id, _importer) + return resolver(id, _importer, undefined, ssr) } return { diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 0d054ba5387978..0da11cff24340f 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -103,7 +103,8 @@ export async function optimizeDeps( config: ResolvedConfig, force = config.server.force, asCommand = false, - newDeps?: Record // missing imports encountered after server has started + newDeps?: Record, // missing imports encountered after server has started + ssr?: boolean ): Promise { config = { ...config, @@ -273,7 +274,7 @@ export async function optimizeDeps( define, plugins: [ ...plugins, - esbuildDepPlugin(flatIdDeps, flatIdToExports, config) + esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) ], ...esbuildOptions }) diff --git a/packages/vite/src/node/optimizer/registerMissing.ts b/packages/vite/src/node/optimizer/registerMissing.ts index 32fdce1526d1ba..e6f1b95d595421 100644 --- a/packages/vite/src/node/optimizer/registerMissing.ts +++ b/packages/vite/src/node/optimizer/registerMissing.ts @@ -11,7 +11,7 @@ const debounceMs = 100 export function createMissingImporterRegisterFn( server: ViteDevServer -): (id: string, resolved: string) => void { +): (id: string, resolved: string, ssr?: boolean) => void { const { logger } = server.config let knownOptimized = server._optimizeDepsMetadata!.optimized let currentMissing: Record = {} @@ -19,7 +19,7 @@ export function createMissingImporterRegisterFn( let pendingResolve: (() => void) | null = null - async function rerun() { + async function rerun(ssr: boolean | undefined) { const newDeps = currentMissing currentMissing = {} @@ -48,7 +48,8 @@ export function createMissingImporterRegisterFn( server.config, true, false, - newDeps + newDeps, + ssr )) knownOptimized = newData!.optimized @@ -84,11 +85,15 @@ export function createMissingImporterRegisterFn( }) } - return function registerMissingImport(id: string, resolved: string) { + return function registerMissingImport( + id: string, + resolved: string, + ssr?: boolean + ) { if (!knownOptimized[id]) { currentMissing[id] = resolved if (handle) clearTimeout(handle) - handle = setTimeout(rerun, debounceMs) + handle = setTimeout(() => rerun(ssr), debounceMs) server._pendingReload = new Promise((r) => { pendingResolve = r }) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 65dea3c50ee2d6..36b364672d23e1 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -145,7 +145,8 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { importer, options, targetWeb, - server + server, + ssr )) && res.id.startsWith(normalizedFsPath) ) { @@ -212,7 +213,9 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { return res } - if ((res = tryNodeResolve(id, importer, options, targetWeb, server))) { + if ( + (res = tryNodeResolve(id, importer, options, targetWeb, server, ssr)) + ) { return res } @@ -361,7 +364,8 @@ export function tryNodeResolve( importer: string | undefined, options: InternalResolveOptions, targetWeb: boolean, - server?: ViteDevServer + server?: ViteDevServer, + ssr?: boolean ): PartialResolvedId | undefined { const { root, dedupe, isBuild } = options const deepMatch = id.match(deepImportRE) @@ -432,7 +436,7 @@ export function tryNodeResolve( } else { // this is a missing import. // queue optimize-deps re-run. - server._registerMissingImport?.(id, resolved) + server._registerMissingImport?.(id, resolved, ssr) } return { id: resolved } } @@ -546,7 +550,7 @@ export function resolvePackageEntry( // resolve exports field with highest priority // using https://github.com/lukeed/resolve.exports if (data.exports) { - entryPoint = resolveExports(data, '.', options) + entryPoint = resolveExports(data, '.', options, targetWeb) } // if exports resolved to .mjs, still resolve other fields. @@ -628,7 +632,8 @@ export function resolvePackageEntry( function resolveExports( pkg: PackageData['data'], key: string, - options: InternalResolveOptions + options: InternalResolveOptions, + targetWeb: boolean ) { const conditions = [options.isProduction ? 'production' : 'development'] if (!options.isRequire) { @@ -638,7 +643,7 @@ function resolveExports( conditions.push(...options.conditions) } return _resolveExports(pkg, key, { - browser: true, + browser: targetWeb, require: options.isRequire, conditions }) @@ -668,7 +673,7 @@ function resolveDeepImport( // map relative based on exports data if (exportsField) { if (isObject(exportsField) && !Array.isArray(exportsField)) { - relativeId = resolveExports(data, relativeId, options) + relativeId = resolveExports(data, relativeId, options, targetWeb) } else { // not exposed relativeId = undefined diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 783a3787858920..8d10ac519a6f3d 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -287,7 +287,9 @@ export interface ViteDevServer { /** * @internal */ - _registerMissingImport: ((id: string, resolved: string) => void) | null + _registerMissingImport: + | ((id: string, resolved: string, ssr: boolean | undefined) => void) + | null /** * @internal */ diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index aa913e104df2ca..b12d06e3a63644 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -49,7 +49,14 @@ export function resolveSSRExternal( let entry let requireEntry try { - entry = tryNodeResolve(id, undefined, resolveOptions, true)?.id + entry = tryNodeResolve( + id, + undefined, + resolveOptions, + true, + undefined, + true + )?.id requireEntry = require.resolve(id, { paths: [root] }) } catch (e) { // resolve failed, assume include