Skip to content

Commit 8328011

Browse files
authoredOct 14, 2022
feat(server): invalidate module with hmr (#10333)
1 parent a9f9d31 commit 8328011

File tree

6 files changed

+69
-14
lines changed

6 files changed

+69
-14
lines changed
 

‎docs/guide/api-javascript.md

+5
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ interface ViteDevServer {
119119
* Fix ssr error stacktrace.
120120
*/
121121
ssrFixStacktrace(e: Error): void
122+
/**
123+
* Triggers HMR for a module in the module graph. You can use the `server.moduleGraph`
124+
* API to retrieve the module to be reloaded. If `hmr` is false, this is a no-op.
125+
*/
126+
reloadModule(module: ModuleNode): Promise<void>
122127
/**
123128
* Start the server.
124129
*/

‎packages/vite/src/node/server/index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ import {
6565
serveStaticMiddleware
6666
} from './middlewares/static'
6767
import { timeMiddleware } from './middlewares/time'
68+
import type { ModuleNode } from './moduleGraph'
6869
import { ModuleGraph } from './moduleGraph'
6970
import { errorMiddleware, prepareError } from './middlewares/error'
7071
import type { HmrOptions } from './hmr'
@@ -245,6 +246,11 @@ export interface ViteDevServer {
245246
* Mutates the given SSR error by rewriting the stacktrace
246247
*/
247248
ssrFixStacktrace(e: Error): void
249+
/**
250+
* Triggers HMR for a module in the module graph. You can use the `server.moduleGraph`
251+
* API to retrieve the module to be reloaded. If `hmr` is false, this is a no-op.
252+
*/
253+
reloadModule(module: ModuleNode): Promise<void>
248254
/**
249255
* Start the server.
250256
*/
@@ -382,6 +388,11 @@ export async function createServer(
382388
ssrRewriteStacktrace(stack: string) {
383389
return ssrRewriteStacktrace(stack, moduleGraph)
384390
},
391+
async reloadModule(module) {
392+
if (serverConfig.hmr !== false && module.file) {
393+
updateModules(module.file, [module], Date.now(), server)
394+
}
395+
},
385396
async listen(port?: number, isRestart?: boolean) {
386397
await startServer(server, port, isRestart)
387398
if (httpServer) {

‎playground/hmr/__tests__/hmr.spec.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -651,11 +651,23 @@ if (!isBuild) {
651651
test('handle virtual module updates', async () => {
652652
await page.goto(viteTestUrl)
653653
const el = await page.$('.virtual')
654-
expect(await el.textContent()).toBe('[success]')
654+
expect(await el.textContent()).toBe('[success]0')
655655
editFile('importedVirtual.js', (code) => code.replace('[success]', '[wow]'))
656656
await untilUpdated(async () => {
657657
const el = await page.$('.virtual')
658658
return await el.textContent()
659659
}, '[wow]')
660660
})
661+
662+
test('invalidate virtual module', async () => {
663+
await page.goto(viteTestUrl)
664+
const el = await page.$('.virtual')
665+
expect(await el.textContent()).toBe('[wow]0')
666+
const btn = await page.$('.virtual-update')
667+
btn.click()
668+
await untilUpdated(async () => {
669+
const el = await page.$('.virtual')
670+
return await el.textContent()
671+
}, '[wow]1')
672+
})
661673
}

‎playground/hmr/hmr.ts

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ text('.dep', depFoo)
1010
text('.nested', nestedFoo)
1111
text('.virtual', virtual)
1212

13+
const btn = document.querySelector('.virtual-update') as HTMLButtonElement
14+
btn.onclick = () => {
15+
if (import.meta.hot) {
16+
import.meta.hot.send('virtual:increment')
17+
}
18+
}
19+
1320
if (import.meta.hot) {
1421
import.meta.hot.accept(({ foo }) => {
1522
console.log('(self-accepting 1) foo is now:', foo)

‎playground/hmr/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
href="./global.css?param=required"
66
/>
77
</div>
8+
<button class="virtual-update">update virtual module</button>
9+
810
<script type="module" src="./hmr.ts"></script>
911
<style>
1012
.import-image {

‎playground/hmr/vite.config.ts

+31-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defineConfig } from 'vite'
2+
import type { Plugin } from 'vite'
23

34
export default defineConfig({
45
experimental: {
@@ -20,18 +21,35 @@ export default defineConfig({
2021
})
2122
}
2223
},
23-
{
24-
name: 'virtual-file',
25-
resolveId(id) {
26-
if (id === 'virtual:file') {
27-
return '\0virtual:file'
28-
}
29-
},
30-
load(id) {
31-
if (id === '\0virtual:file') {
32-
return 'import { virtual } from "/importedVirtual.js"; export { virtual };'
33-
}
34-
}
35-
}
24+
virtualPlugin()
3625
]
3726
})
27+
28+
function virtualPlugin(): Plugin {
29+
let num = 0
30+
return {
31+
name: 'virtual-file',
32+
resolveId(id) {
33+
if (id === 'virtual:file') {
34+
return '\0virtual:file'
35+
}
36+
},
37+
load(id) {
38+
if (id === '\0virtual:file') {
39+
return `\
40+
import { virtual as _virtual } from "/importedVirtual.js";
41+
export const virtual = _virtual + '${num}';`
42+
}
43+
},
44+
configureServer(server) {
45+
server.ws.on('virtual:increment', async () => {
46+
const mod = await server.moduleGraph.getModuleByUrl('\0virtual:file')
47+
console.log(mod)
48+
if (mod) {
49+
num++
50+
server.reloadModule(mod)
51+
}
52+
})
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)
Please sign in to comment.