Skip to content

Commit

Permalink
fix: keep track of ssr version of imported modules separately (#11973)
Browse files Browse the repository at this point in the history
  • Loading branch information
shYkiSto authored Jun 15, 2023
1 parent 1fd9919 commit 8fe6952
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 6 deletions.
25 changes: 21 additions & 4 deletions packages/vite/src/node/server/moduleGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export class ModuleNode {
info?: ModuleInfo
meta?: Record<string, any>
importers = new Set<ModuleNode>()
importedModules = new Set<ModuleNode>()
clientImportedModules = new Set<ModuleNode>()
ssrImportedModules = new Set<ModuleNode>()
acceptedHmrDeps = new Set<ModuleNode>()
acceptedHmrExports: Set<string> | null = null
importedBindings: Map<string, Set<string>> | null = null
Expand All @@ -46,6 +47,14 @@ export class ModuleNode {
this.isSelfAccepting = false
}
}

get importedModules(): Set<ModuleNode> {
const importedModules = new Set(this.clientImportedModules)
for (const module of this.ssrImportedModules) {
importedModules.add(module)
}
return importedModules
}
}

export type ResolvedUrl = [
Expand Down Expand Up @@ -169,7 +178,7 @@ export class ModuleGraph {
ssr?: boolean,
): Promise<Set<ModuleNode> | undefined> {
mod.isSelfAccepting = isSelfAccepting
const prevImports = mod.importedModules
const prevImports = ssr ? mod.ssrImportedModules : mod.clientImportedModules
let noLongerImported: Set<ModuleNode> | undefined

let resolvePromises = []
Expand All @@ -195,11 +204,19 @@ export class ModuleGraph {
await Promise.all(resolvePromises)
}

const nextImports = (mod.importedModules = new Set(resolveResults))
const nextImports = new Set(resolveResults)
if (ssr) {
mod.ssrImportedModules = nextImports
} else {
mod.clientImportedModules = nextImports
}

// remove the importer from deps that were imported but no longer are.
prevImports.forEach((dep) => {
if (!nextImports.has(dep)) {
if (
!mod.clientImportedModules.has(dep) &&
!mod.ssrImportedModules.has(dep)
) {
dep.importers.delete(mod)
if (!dep.importers.size) {
// dependency no longer imported
Expand Down
35 changes: 33 additions & 2 deletions playground/ssr-deps/__tests__/ssr-deps.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, test } from 'vitest'
import { describe, expect, test } from 'vitest'
import { port } from './serve'
import { getColor, page } from '~utils'
import { editFile, getColor, isServe, page, untilUpdated } from '~utils'

const url = `http://localhost:${port}`

Expand Down Expand Up @@ -121,3 +121,34 @@ test('import css library', async () => {
await page.goto(url)
expect(await page.textContent('.module-condition')).toMatch('[success]')
})

describe.runIf(isServe)('hmr', () => {
test('handle isomorphic module updates', async () => {
await page.goto(url)

expect(await page.textContent('.isomorphic-module-server')).toMatch(
'[server]',
)
// Allowing additional time for this element to be filled in
// by a client script that is loaded using dynamic import
await untilUpdated(async () => {
return page.textContent('.isomorphic-module-browser')
}, '[browser]')

editFile('src/isomorphic-module-browser.js', (code) =>
code.replace('[browser]', '[browser-hmr]'),
)
await page.waitForNavigation()
await untilUpdated(async () => {
return page.textContent('.isomorphic-module-browser')
}, '[browser-hmr]')

editFile('src/isomorphic-module-server.js', (code) =>
code.replace('[server]', '[server-hmr]'),
)
await page.waitForNavigation()
await untilUpdated(async () => {
return page.textContent('.isomorphic-module-server')
}, '[server-hmr]')
})
})
10 changes: 10 additions & 0 deletions playground/ssr-deps/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,15 @@ <h1>SSR Dependencies</h1>
// hydration scripts
import '@vitejs/test-css-lib'
</script>
<script type="module">
// Using dynamic import, so the module is transformed when browser actually
// requests it. This essentially disables pre-transform optimization that's
// crucial to trigger a race condition, covered by the test case introduced
// in https://github.com/vitejs/vite/pull/11973
import('virtual:isomorphic-module').then(({ default: message }) => {
document.querySelector('.isomorphic-module-browser').textContent =
message
})
</script>
</body>
</html>
17 changes: 17 additions & 0 deletions playground/ssr-deps/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ export async function createServer(root = process.cwd(), hmrPort) {
}
},
},
{
name: 'virtual-isomorphic-module',
resolveId(id) {
if (id === 'virtual:isomorphic-module') {
return '\0virtual:isomorphic-module'
}
},
load(id, { ssr }) {
if (id === '\0virtual:isomorphic-module') {
if (ssr) {
return 'export { default } from "/src/isomorphic-module-server.js";'
} else {
return 'export { default } from "/src/isomorphic-module-browser.js";'
}
}
},
},
],
})
// use vite's connect instance as middleware
Expand Down
5 changes: 5 additions & 0 deletions playground/ssr-deps/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import optimizedCjsWithNestedExternal from '@vitejs/test-optimized-cjs-with-nest
import { setMessage } from '@vitejs/test-external-entry/entry'
setMessage('Hello World!')
import externalUsingExternalEntry from '@vitejs/test-external-using-external-entry'
import isomorphicModuleMessage from 'virtual:isomorphic-module'

export async function render(url, rootDir) {
let html = ''
Expand Down Expand Up @@ -90,5 +91,9 @@ export async function render(url, rootDir) {

html += `\n<p class="module-condition">${moduleConditionMessage}</p>`

html += `\n<p class="isomorphic-module-server">${isomorphicModuleMessage}</p>`

html += `\n<p class="isomorphic-module-browser"></p>`

return html + '\n'
}
3 changes: 3 additions & 0 deletions playground/ssr-deps/src/isomorphic-module-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const message = 'message from isomorphic-module (browser): [browser]'

export default message
3 changes: 3 additions & 0 deletions playground/ssr-deps/src/isomorphic-module-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const message = 'message from isomorphic-module (server): [server]'

export default message

0 comments on commit 8fe6952

Please sign in to comment.