¿Qué es exactamente el reemplazo de módulo caliente en Webpack?

245

He leído algunas páginas sobre Hot Module Replacement en Webpack.
Incluso hay una aplicación de muestra que lo usa .

He leído todo esto y todavía no entiendo la idea.

¿Qué puedo hacer con eso?

  1. ¿Se supone que solo debe usarse en el desarrollo y no en la producción?
  2. ¿Es como LiveReload, pero tienes que administrarlo tú mismo?
  3. ¿WebpackDevServer está integrado con LiveReload de alguna manera?

Supongamos que quiero actualizar mis módulos CSS (una hoja de estilo) y JS cuando los guardo en el disco, sin volver a cargar la página y sin usar complementos como LiveReload. ¿Es esto algo en lo que me puede ayudar el Hot Module Replacement? ¿Qué tipo de trabajo necesito hacer y qué ya proporciona HMR?

Dan Abramov
fuente
HMR con Webpack es casi tan bueno como esto: medium.com/@the1mills/…
Alexander Mills

Respuestas:

408

Primero quiero señalar que el reemplazo de módulo caliente (HMR) sigue siendo una característica experimental.

HMR es una forma de intercambiar módulos en una aplicación en ejecución (y agregar / eliminar módulos). Básicamente, puede actualizar los módulos modificados sin una recarga completa de la página.

Documentación

Pre requisitos:

No es tanto para HMR, pero aquí están los enlaces:

Agregaré estas respuestas a la documentación.

¿Como funciona?

Desde la vista de la aplicación

El código de la aplicación solicita al tiempo de ejecución de HMR que busque actualizaciones. El tiempo de ejecución de HMR descarga las actualizaciones (asíncrono) y le dice al código de la aplicación que hay una actualización disponible. El código de la aplicación solicita al tiempo de ejecución de HMR que aplique las actualizaciones. El tiempo de ejecución de HMR aplica las actualizaciones (sincronización). El código de la aplicación puede o no requerir la interacción del usuario en este proceso (usted decide).

Desde la vista del compilador (paquete web)

Además de los activos normales, el compilador debe emitir la "Actualización" para permitir la actualización de una versión anterior a esta versión. La "Actualización" contiene dos partes:

  1. el manifiesto de actualización (json)
  2. uno o varios fragmentos de actualización (js)

El manifiesto contiene el nuevo hash de compilación y una lista de todos los fragmentos de actualización (2).

Los fragmentos de actualización contienen código para todos los módulos actualizados en este fragmento (o una marca si se eliminó un módulo).

El compilador además se asegura de que los módulos y los identificadores de fragmentos sean consistentes entre estas compilaciones. Utiliza un archivo json de "registros" para almacenarlos entre compilaciones (o los almacena en la memoria).

Desde la vista del módulo

HMR es una función opcional, por lo que solo afecta a los módulos que contienen código HMR. La documentación describe la API que está disponible en módulos. En general, el desarrollador del módulo escribe manejadores a los que se llama cuando se actualiza una dependencia de este módulo. También pueden escribir un controlador que se llama cuando se actualiza este módulo.

En la mayoría de los casos, no es obligatorio escribir código HMR en cada módulo. Si un módulo no tiene controladores HMR, la actualización aparece. Esto significa que un solo controlador puede manejar actualizaciones para un árbol de módulos completo. Si se actualiza un solo módulo en este árbol, el árbol del módulo completo se vuelve a cargar (solo se recarga, no se transfiere).

Desde la vista de tiempo de ejecución de HMR (técnica)

Se emite un código adicional para el tiempo de ejecución del sistema del módulo para rastrear el módulo parentsy children.

En el lado de la administración, el tiempo de ejecución admite dos métodos: checky apply.

A checkhace una solicitud HTTP al manifiesto de actualización. Cuando esta solicitud falla, no hay actualizaciones disponibles. De lo contrario, la lista de fragmentos actualizados se compara con la lista de fragmentos cargados actualmente. Para cada fragmento cargado, se descarga el fragmento de actualización correspondiente. Todas las actualizaciones del módulo se almacenan en el tiempo de ejecución como actualizaciones. El tiempo de ejecución cambia al readyestado, lo que significa que se ha descargado una actualización y está lista para aplicarse.

Para cada nueva solicitud de fragmento en el estado listo, también se descarga el fragmento de actualización.

El applymétodo marca todos los módulos actualizados como no válidos. Para cada módulo no válido, debe haber un controlador de actualización en el módulo o controladores de actualización en cada padre. De lo contrario, el inválido aparece y marca a todos los padres como inválidos también. Este proceso continúa hasta que no ocurra más "burbujeo". Si aparece en un punto de entrada, el proceso falla.

Ahora todos los módulos no válidos se eliminan (eliminan el controlador) y se descargan. Luego se actualiza el hash actual y se llama a todos los manejadores "aceptar". El tiempo de ejecución vuelve al idleestado y todo continúa de manera normal.

fragmentos de actualización generados

¿Qué puedo hacer con eso?

Puede usarlo en desarrollo como reemplazo de LiveReload. En realidad, el servidor webpack-dev admite un modo dinámico que intenta actualizar con HMR antes de intentar volver a cargar toda la página. Solo necesita agregar el webpack/hot/dev-serverpunto de entrada y llamar al servidor de desarrollo con --hot.

También puede usarlo en producción como mecanismos de actualización. Aquí debe escribir su propio código de administración que integra HMR con su aplicación.

Algunos cargadores ya generan módulos que se pueden actualizar en caliente. Por ejemplo, style-loaderpueden intercambiar la hoja de estilo. No necesitas hacer nada especial.

Supongamos que quiero actualizar mis módulos CSS (una hoja de estilo) y JS cuando los guardo en el disco, sin volver a cargar la página y sin usar complementos como LiveReload. ¿Es esto algo en lo que me puede ayudar el Hot Module Replacement?

si

¿Qué tipo de trabajo necesito hacer y qué ya proporciona HMR?

Aquí hay un pequeño ejemplo: https://webpack.js.org/guides/hot-module-replacement/

Un módulo solo puede actualizarse si lo "acepta". Por lo tanto, necesita module.hot.acceptel módulo en los padres o los padres de los padres ... por ejemplo, un enrutador es un buen lugar o una subvista.

Si solo desea usarlo con el servidor webpack-dev, simplemente agregue webpack/hot/dev-servercomo punto de entrada. De lo contrario, necesita un código de administración de HMR que llame checky apply.

Opinión: ¿Qué lo hace tan genial?

  • Es LiveReload pero para cada tipo de módulo.
  • Puedes usarlo en producción.
  • Las actualizaciones respetan su División de código y solo descargan actualizaciones para las partes usadas de su aplicación.
  • Puede usarlo para una parte de su aplicación y no afecta a otros módulos
  • Si HMR está deshabilitado, el compilador elimina todo el código HMR (lo envuelve if(module.hot)).

Advertencias

  • Es experimental y no se ha probado tan bien.
  • Espera algunos errores.
  • Teóricamente utilizable en producción, pero puede ser demasiado temprano para usarlo en algo serio.
  • Las ID del módulo deben rastrearse entre las compilaciones, por lo que debe almacenarlas ( records).
  • El optimizador ya no puede optimizar las ID de los módulos después de la primera compilación. Un poco de impacto en el tamaño del paquete.
  • El código de tiempo de ejecución de HMR aumenta el tamaño del paquete.
  • Para el uso de producción, se requieren pruebas adicionales para probar los controladores HMR. Esto podría ser bastante difícil.
Tobias K.
fuente
145
Una respuesta infernal.
Dan Abramov
13
Gracias de nuevo por la explicación, hice un video que muestra el poder de HMR para editar en vivo una aplicación React.
Dan Abramov
1
bastante genial ... pensé en hacer un cargador de reacción que agregue HMR y carga asíncrona para reaccionar componentes.
Tobias K.
44
Copié esta respuesta en la documentación: webpack.github.io/docs/hot-module-replacement-with-webpack.html
Tobias K.
2
Puede detectar errores en los módulos actualizados, cuando requireajusta el controlador de actualización HMR en un bloque try-catch.
Tobias K.
10

La respuesta aceptada explica que todo es correcto de todos modos, la siguiente descripción ayuda a comprender qué es HMR rápidamente.

El reemplazo de Hot Module es una de las técnicas más nuevas en el desarrollo de JavaScript que atrae la atención de los desarrolladores. Ayuda al desarrollo al reducir el número de actualizaciones de página al reemplazar los módulos con cambios en tiempo de ejecución.

Mientras buscaba sobre HMR, encontré un artículo que explica el concepto en Internet, puede obtenerlo desde aquí y agregar una imagen GIF que explica el concepto sin mucha explicación.

Aquí está en funcionamiento: observe que el temporizador no se restablece a 0 como lo haría después de una recarga de página, y css también cambia la actualización automática. GIF de reemplazo de módulo caliente

Webpack ayuda a lograr HMR. Puedes encontrar documentos aquí

Ayuda a lograr el seguimiento

  • Conservar el estado de la aplicación que se pierde durante una recarga completa.

  • Ahorre un valioso tiempo de desarrollo actualizando solo lo que ha cambiado.

  • Ajusta el estilo más rápido, casi comparable a los estilos cambiantes en el depurador del navegador.

Aquí está la guía webpack para lograr HMR

samuelj90
fuente