first
This commit is contained in:
200
.cursor/skills/vite/references/features-hmr.md
Normal file
200
.cursor/skills/vite/references/features-hmr.md
Normal file
@@ -0,0 +1,200 @@
|
||||
---
|
||||
name: features-hmr
|
||||
description: Vite's Hot Module Replacement (HMR) client API
|
||||
---
|
||||
|
||||
# HMR API
|
||||
|
||||
The HMR API is exposed via `import.meta.hot`. Primarily for framework and tooling authors.
|
||||
|
||||
## Conditional Guard
|
||||
|
||||
Always guard HMR code for tree-shaking in production:
|
||||
|
||||
```ts
|
||||
if (import.meta.hot) {
|
||||
// HMR code
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript Support
|
||||
|
||||
Add to `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": ["vite/client"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Self-Accepting Module
|
||||
|
||||
Module handles its own updates:
|
||||
|
||||
```ts
|
||||
export const count = 1
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept((newModule) => {
|
||||
if (newModule) {
|
||||
console.log('updated: count is now', newModule.count)
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Accept Dependency Updates
|
||||
|
||||
React to changes in dependencies without self-reload:
|
||||
|
||||
```ts
|
||||
import { foo } from './foo.js'
|
||||
|
||||
foo()
|
||||
|
||||
if (import.meta.hot) {
|
||||
// Single dependency
|
||||
import.meta.hot.accept('./foo.js', (newFoo) => {
|
||||
newFoo?.foo()
|
||||
})
|
||||
|
||||
// Multiple dependencies
|
||||
import.meta.hot.accept(
|
||||
['./foo.js', './bar.js'],
|
||||
([newFooModule, newBarModule]) => {
|
||||
// Handle updates
|
||||
}
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Cleanup on Update
|
||||
|
||||
Clean up side effects before module is replaced:
|
||||
|
||||
```ts
|
||||
function setupSideEffect() {
|
||||
const interval = setInterval(() => {}, 1000)
|
||||
return interval
|
||||
}
|
||||
|
||||
const interval = setupSideEffect()
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.dispose((data) => {
|
||||
clearInterval(interval)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Prune Callback
|
||||
|
||||
Called when module is no longer imported:
|
||||
|
||||
```ts
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.prune((data) => {
|
||||
// Cleanup when module is removed from page
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Persistent Data
|
||||
|
||||
Pass data between module instances:
|
||||
|
||||
```ts
|
||||
if (import.meta.hot) {
|
||||
// Mutate properties, don't reassign data itself
|
||||
import.meta.hot.data.count = (import.meta.hot.data.count || 0) + 1
|
||||
}
|
||||
```
|
||||
|
||||
## Invalidate
|
||||
|
||||
Force propagation to importers:
|
||||
|
||||
```ts
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept((module) => {
|
||||
if (cannotHandleUpdate(module)) {
|
||||
import.meta.hot.invalidate() // Propagate to importers
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## HMR Events
|
||||
|
||||
Listen to built-in events:
|
||||
|
||||
```ts
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.on('vite:beforeUpdate', (payload) => {
|
||||
console.log('Update incoming')
|
||||
})
|
||||
|
||||
import.meta.hot.on('vite:afterUpdate', (payload) => {
|
||||
console.log('Update applied')
|
||||
})
|
||||
|
||||
import.meta.hot.on('vite:beforeFullReload', () => {
|
||||
console.log('Full reload')
|
||||
})
|
||||
|
||||
import.meta.hot.on('vite:error', (error) => {
|
||||
console.error('HMR error', error)
|
||||
})
|
||||
|
||||
import.meta.hot.on('vite:ws:connect', () => {
|
||||
console.log('WebSocket connected')
|
||||
})
|
||||
|
||||
import.meta.hot.on('vite:ws:disconnect', () => {
|
||||
console.log('WebSocket disconnected')
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Events
|
||||
|
||||
Send events to server:
|
||||
|
||||
```ts
|
||||
// Client
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.send('my:event', { msg: 'Hello from client' })
|
||||
}
|
||||
```
|
||||
|
||||
Receive from server:
|
||||
|
||||
```ts
|
||||
// Client
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.on('my:response', (data) => {
|
||||
console.log(data.msg)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript for Custom Events
|
||||
|
||||
```ts
|
||||
// events.d.ts
|
||||
import 'vite/types/customEvent.d.ts'
|
||||
|
||||
declare module 'vite/types/customEvent.d.ts' {
|
||||
interface CustomEventMap {
|
||||
'my:event': { msg: string }
|
||||
'my:response': { msg: string }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
Source references:
|
||||
- https://vite.dev/guide/api-hmr.html
|
||||
-->
|
||||
Reference in New Issue
Block a user