Skip to content

API de HMR

Nota

Esta es la API cliente de HMR. Para manejar actualizaciones HMR en los plugins, dale un vistazo a handleHotUpdate.

La API HMR está pensada para autores de marco de trabajo y autores de herramientas. Como usuario final, HMR ya está siendo manejado para ti en las plantillas de inicio del marco de trabajo específico.

Vite expone su API HMR a través del objeto especial import.meta.hot:

ts
interface ImportMeta {
  readonly 
hot
?: ViteHotContext
} interface ViteHotContext { readonly
data
: any
accept
(): void
accept
(
cb
: (
mod
:
ModuleNamespace
| undefined) => void): void
accept
(
dep
: string,
cb
: (
mod
:
ModuleNamespace
| undefined) => void): void
accept
(
deps
: readonly string[],
cb
: (
mods
:
Array
<
ModuleNamespace
| undefined>) => void
): void
dispose
(
cb
: (
data
: any) => void): void
prune
(
cb
: (
data
: any) => void): void
invalidate
(
message
?: string): void
on
<
T
extends string>(
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
}

Encapsulamiento Condicional Requerido

Primero que nada, debes asegurarte de tener todos los llamados a la API HMR en un bloque condicional, para que el código pueda ser descartado en producción:

js
if (import.meta.hot) {
  // Código HMR
}

IntelliSense para TypeScript

Vite proporciona definiciones de tipos para import.meta.hot en vite/client.d.ts. Puedes crear un env.d.ts en el directorio src para que TypeScript tome las definiciones de tipo:

ts
/// <reference types="vite/client" />

hot.accept(cb)

Para que un módulo pueda ser actualizado, debes utilizar import.meta.hot.accept() con un callback que recibe el módulo actualizado:

js
export const 
count
= 1
if (import.meta.
hot
) {
import.meta.
hot
.
accept
((
newModule
) => {
if (
newModule
) {
// newModule no está definido cuando ocurrió el SyntaxError
console
.
log
('actualizado: count ahora es ',
newModule
.count)
} }) }

Un módulo que "acepta" actualizaciones instantáneas es considerado un Límite HMR.

Ten en cuenta que el HMR de Vite en realidad no intercambia el módulo importado originalmente: si los límites de un módulo HMR reexportan las importaciones desde un dep, entonces es responsable de actualizar esas reexportaciones (y estas exportaciones deben usar let). Además, los importadores relacionados con los límites del modulo no serán notificados de este cambio. Esta implementación simplificada de HMR es suficiente para la mayoría de los casos de uso de desarrollo, al tiempo que nos permite omitir el costoso trabajo de generar módulos proxy.

Vite requiere que la llamada a esta función aparezca como import.meta.hot.accept( (sensible a los espacios en blanco) en el código fuente para que el módulo acepte la actualización. Este es un requisito del análisis estático que hace Vite para habilitar el soporte de HMR para un módulo.

hot.accept(deps, cb)

Un módulo también puede aceptar actualizaciones de dependencias directas sin tener que recargarse:

js
import { 
foo
} from './foo.js'
foo
()
if (import.meta.
hot
) {
import.meta.
hot
.
accept
('./foo.js', (
newFoo
) => {
// el callback recibe el módulo './foo.js' actualizado
newFoo
?.foo()
}) // Puede aceptar un array de módulos de dependencia: import.meta.
hot
.
accept
(
['./foo.js', './bar.js'], ([
newFooModule
,
newBarModule
]) => {
// El callback recibe un array donde solo el módulo actualizado // no es nulo. Si la actualización no fue exitosa // (por ejemplo, error de sintaxis), el array estará vacío }, ) }

hot.dispose(cb)

Un módulo de autoaceptación o un módulo que espera ser aceptado por otros puede usar hot.dispose para eliminar cualquier efecto secundario persistente creado por su copia actualizada:

js
function 
setupSideEffect
() {}
setupSideEffect
()
if (import.meta.
hot
) {
import.meta.
hot
.
dispose
((
data
) => {
// eliminar los efectos secundarios }) }

hot.prune(cb)

Registra una callback que se invoca cuando el módulo ya no se importe en la página. En comparación con hot.dispose, esto se puede usar si el código fuente limpia los efectos secundarios por sí mismo en las actualizaciones y solo necesitas limpiar cuando se elimina de la página. Vite actualmente usa esto para importaciones .css.

js
function 
setupOrReuseSideEffect
() {}
setupOrReuseSideEffect
()
if (import.meta.
hot
) {
import.meta.
hot
.
prune
((
data
) => {
// eliminar los efectos secundarios }) }

hot.data

El objeto import.meta.hot.data se mantiene en diferentes instancias del mismo módulo actualizado. Se puede utilizar para pasar información de una versión anterior del módulo a la siguiente.

Ten en cuenta que no se soporta la reasignación de data en sí. En su lugar, debes mutar las propiedades del objeto data para que se preserve la información agregada por otros manejadores.

js
// ok
import.meta.
hot
.
data
.someValue = 'hello'
// no soportado import.meta.
hot
.
data
= {
someValue
: 'hello' }

hot.decline()

Esto es actualmente un noop y está ahí para compatibilidad con versiones anteriores. Esto podría cambiar en el futuro si hay un nuevo uso para él. Para indicar que el módulo no se puede actualizar en caliente, utiliza hot.invalidate().

hot.invalidate(message?: string)

Un módulo de autoaceptación puede detectar durante el tiempo de ejecución de que no puede manejar una actualización de HMR y, por lo tanto, la actualización debe propagarse forzosamente a los importadores. Al llamar a import.meta.hot.invalidate(), el servidor HMR invalidará los importadores del invocador, como si no se aceptara a sí misma. Esto registrará un mensaje tanto en la consola del navegador como en la terminal. Puede pasar un mensaje para dar algo de contexto sobre por qué ocurrió la invalidación.

Ten en cuenta que siempre debes llamar a import.meta.hot.accept incluso si planeas invocar a invalidate inmediatamente después, o de lo contrario, el cliente HMR no escuchará los cambios futuros en el módulo de autoaceptación. Para comunicar la intención claramente, recomendamos llamar a invalidate dentro de la devolución de llamada accept así:

js
import.meta.
hot
.
accept
((
module
) => {
// Puedes usar la nueva instancia del módulo para decidir si invalidar. if (cannotHandleUpdate(
module
)) {
import.meta.
hot
.
invalidate
()
} })

hot.off(event, cb)

Elimina el callback de los listeners de eventos.

hot.on(event, cb)

Escucha un evento HMR.

Los siguientes eventos HMR son enviados por Vite automáticamente:

  • 'vite:beforeUpdate' cuando se va a aplicar una actualización (por ejemplo, se reemplazará un módulo).
  • 'vite:afterUpdate' cuando se aplicó una actualización (por ejemplo, se reemplazó un módulo).
  • 'vite:beforeFullReload' cuando una recarga completa está a punto de ser ejecutada.
  • 'vite:beforePrune' cuando los módulos que ya no se necesitan están a punto de ser eliminados.
  • 'vite:invalidate' cuando un módulo es invalidado con import.meta.hot.invalidate()
  • 'vite:error' cuando un error ocurre (Por ejemplo error de sintaxis).
  • 'vite:ws:disconnect' cuando la conexión WebSocket se pierde
  • 'vite:ws:connect' cuando la conexión WebScocket se (re)establece

Los eventos HMR personalizados también se pueden enviar desde plugins. Dale un vistazo a handleHotUpdate para más detalles.

hot.send(event, data)

Envía eventos personalizados al servidor de desarrollo de Vite.

Si se llama antes de conectarse, los datos se almacenarán en búfer y se enviarán una vez que se establezca la conexión.

Consulta Comunicación cliente-servidor para obtener más detalles, incluyendo una sección sobre Typing Custom Events.

Lecturas adicionales

Si deseas aprender más sobre cómo utilizar la API de HMR y cómo funciona internamente, consulta estos recursos:

Publicado bajo licencia MIT. (e6f4382f)