Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/guide/api-hmr.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ interface ViteHotContext {
event: T,
cb: (payload: InferCustomEventPayload<T>) => void,
): void
off<T extends string>(
event: T,
cb: (payload: InferCustomEventPayload<T>) => void,
): void
send<T extends string>(event: T, data?: InferCustomEventPayload<T>): void
}
```
Expand Down Expand Up @@ -181,6 +185,10 @@ The following HMR events are dispatched by Vite automatically:

Custom HMR events can also be sent from plugins. See [handleHotUpdate](./api-plugin#handlehotupdate) for more details.

## `hot.off(event, cb)`

Remove callback from the event listeners

## `hot.send(event, data)`

Send custom events back to Vite's dev server.
Expand Down
18 changes: 18 additions & 0 deletions packages/vite/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,24 @@ export function createHotContext(ownerPath: string): ViteHotContext {
addToMap(newListeners)
},

// remove a custom event
off(event, cb) {
const removeFromMap = (map: Map<string, any[]>) => {
const existing = map.get(event)
if (existing === undefined) {
return
}
const pruned = existing.filter((l) => l !== cb)
if (pruned.length === 0) {
map.delete(event)
return
}
map.set(event, pruned)
}
removeFromMap(customListenersMap)
removeFromMap(newListeners)
},

send(event, data) {
messageBuffer.push(JSON.stringify({ type: 'custom', event, data }))
sendMessageBuffer()
Expand Down
4 changes: 4 additions & 0 deletions packages/vite/types/hot.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ export interface ViteHotContext {
event: T,
cb: (payload: InferCustomEventPayload<T>) => void,
): void
off<T extends string>(
event: T,
cb: (payload: InferCustomEventPayload<T>) => void,
): void
send<T extends string>(event: T, data?: InferCustomEventPayload<T>): void
}
8 changes: 8 additions & 0 deletions playground/hmr/__tests__/hmr.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ if (!isBuild) {
await untilUpdated(() => el.textContent(), 'edited')
})

test('plugin hmr remove custom events', async () => {
const el = await page.$('.toRemove')
editFile('customFile.js', (code) => code.replace('custom', 'edited'))
await untilUpdated(() => el.textContent(), 'edited')
editFile('customFile.js', (code) => code.replace('edited', 'custom'))
await untilUpdated(() => el.textContent(), 'edited')
})

test('plugin client-server communication', async () => {
const el = await page.$('.custom-communication')
await untilUpdated(() => el.textContent(), '3')
Expand Down
7 changes: 7 additions & 0 deletions playground/hmr/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ if (import.meta.hot) {
text('.custom', msg)
})

import.meta.hot.on('custom:remove', removeCb)

// send custom event to server to calculate 1 + 2
import.meta.hot.send('custom:remote-add', { a: 1, b: 2 })
import.meta.hot.on('custom:remote-add-result', ({ result }) => {
Expand All @@ -118,3 +120,8 @@ if (import.meta.hot) {
function text(el, text) {
document.querySelector(el).textContent = text
}

function removeCb({ msg }) {
text('.toRemove', msg)
import.meta.hot.off('custom:remove', removeCb)
}
1 change: 1 addition & 0 deletions playground/hmr/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<div class="dep"></div>
<div class="nested"></div>
<div class="custom"></div>
<div class="toRemove"></div>
<div class="virtual"></div>
<div class="invalidation"></div>
<div class="custom-communication"></div>
Expand Down
1 change: 1 addition & 0 deletions playground/hmr/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default defineConfig({
const content = await read()
const msg = content.match(/export const msg = '(\w+)'/)[1]
server.ws.send('custom:foo', { msg })
server.ws.send('custom:remove', { msg })
}
},
configureServer(server) {
Expand Down