Skip to content

Commit

Permalink
fix(ssr): avoid duplicate ssr module instantiation on shared imports
Browse files Browse the repository at this point in the history
partial fix #2060
  • Loading branch information
yyx990803 committed Feb 22, 2021
1 parent 84d17fc commit a763ffd
Showing 1 changed file with 31 additions and 6 deletions.
37 changes: 31 additions & 6 deletions packages/vite/src/node/ssr/ssrModuleLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ interface SSRContext {
global: NodeJS.Global
}

type SSRModule = Record<string, any>

const pendingModules = new Map<string, Promise<SSRModule>>()

export async function ssrLoadModule(
url: string,
server: ViteDevServer,
context: SSRContext = { global },
urlStack: string[] = []
): Promise<Record<string, any>> {
): Promise<SSRModule> {
url = unwrapId(url)

if (urlStack.includes(url)) {
Expand All @@ -31,6 +35,27 @@ export async function ssrLoadModule(
return {}
}

// when we instantiate multiple dependency modules in parallel, they may
// point to shared modules. We need to avoid duplicate instantiation attempts
// by register every module as pending synchronously so that all subsequent
// request to that module are simply waiting on the same promise.
const pending = pendingModules.get(url)
if (pending) {
return pending
}

const modulePromise = instantiateModule(url, server, context, urlStack)
pendingModules.set(url, modulePromise)
modulePromise.then(() => pendingModules.delete(url))
return modulePromise
}

async function instantiateModule(
url: string,
server: ViteDevServer,
context: SSRContext = { global },
urlStack: string[] = []
): Promise<SSRModule> {
const { moduleGraph } = server
const mod = await moduleGraph.ensureEntryFromUrl(url)

Expand All @@ -46,6 +71,11 @@ export async function ssrLoadModule(
throw new Error(`failed to load module for ssr: ${url}`)
}

const ssrModule = {
[Symbol.toStringTag]: 'Module'
}
Object.defineProperty(ssrModule, '__esModule', { value: true })

const isExternal = (dep: string) => dep[0] !== '.' && dep[0] !== '/'

await Promise.all(
Expand All @@ -56,11 +86,6 @@ export async function ssrLoadModule(
})
)

const ssrModule = {
[Symbol.toStringTag]: 'Module'
}
Object.defineProperty(ssrModule, '__esModule', { value: true })

const ssrImportMeta = { url }

const ssrImport = (dep: string) => {
Expand Down

0 comments on commit a763ffd

Please sign in to comment.