¿Qué es exactamente el reemplazo de módulo en caliente en Webpack?
He leído algunas páginas sobre el reemplazo de módulos en caliente en Webpack.
Incluso hay una aplicación de muestra que lo utiliza .
He leído todo esto y todavía no entiendo la idea.
¿Qué puedo hacer con él?
- ¿Se supone que solo debe usarse en desarrollo y no en producción?
- ¿Es como LiveReload, pero tienes que gestionarlo tú mismo?
- ¿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 recargar la página y sin usar complementos como LiveReload. ¿Es esto algo en lo que el reemplazo del módulo en caliente puede ayudarme? ¿Qué tipo de trabajo necesito hacer y qué ofrece ya HMR?
Primero, quiero señalar que el reemplazo de módulo en caliente (HMR) sigue siendo una función 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 tener que recargar la página completa.
Documentación
Pre requisitos:
- Uso de complementos: https://webpack.js.org/concepts/plugins/
- División de código: https://webpack.js.org/guides/code-splitting/
- servidor-dev-webpack: https://webpack.js.org/configuration/dev-server/
No es tanto para HMR, pero aquí están los enlaces:
- Ejemplo: https://webpack.js.org/guides/hot-module-replacement/
- API: https://webpack.js.org/concepts/hot-module-replacement/
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 indica 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 actualizaciones. El tiempo de ejecución de HMR aplica las actualizaciones (sincronización). El código de la aplicación puede requerir o no 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 necesita emitir la "Actualización" para permitir la actualización de una versión anterior a esta versión. La "Actualización" contiene dos partes:
- el manifiesto de actualización (json)
- 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 identificadores de módulo y fragmento sean coherentes 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 controladores que se llaman cuando se actualiza una dependencia de este módulo. También pueden escribir un controlador al 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 único controlador puede manejar actualizaciones para un árbol de módulos completo. Si se actualiza un solo módulo en este árbol, se recarga el árbol de módulos completo (solo se recarga, no se transfiere).
Desde la vista del tiempo de ejecución de HMR (técnico)
Se emite código adicional para que el tiempo de ejecución del sistema del módulo rastree el módulo parents
y children
.
Desde el punto de vista de la administración, el tiempo de ejecución admite dos métodos: check
y apply
.
A check
realiza una solicitud HTTP al manifiesto de actualización. Cuando esta solicitud falla, no hay ninguna actualización disponible. 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 ready
estado, lo que significa que se ha descargado una actualización y está lista para aplicarse.
Para cada nueva solicitud de fragmento en estado listo, también se descarga el fragmento de actualización.
El apply
método marca todos los módulos actualizados como no válidos. Para cada módulo no válido, es necesario que haya 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 se produzcan más "burbujas". Si burbujea hasta un punto de entrada, el proceso falla.
Ahora todos los módulos no válidos se eliminan (controlador de eliminación) y se descargan. Luego se actualiza el hash actual y se llama a todos los controladores de "aceptación". El tiempo de ejecución vuelve al idle
estado y todo continúa con normalidad.
¿Qué puedo hacer con él?
Puedes usarlo en desarrollo como reemplazo de LiveReload. En realidad, el servidor webpack-dev-server admite un modo activo que intenta actualizar con HMR antes de intentar recargar toda la página. Solo necesita agregar el webpack/hot/dev-server
punto de entrada y llamar al servidor de desarrollo con --hot
.
También puedes usarlo en producción como mecanismo de actualización. Aquí debe escribir su propio código de administración que integre HMR con su aplicación.
Algunos cargadores ya generan módulos que se pueden actualizar en caliente. Por ejemplo, style-loader
pueden 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 recargar la página y sin usar complementos como LiveReload. ¿Es esto algo en lo que el reemplazo del módulo en caliente puede ayudarme?
Sí
¿Qué tipo de trabajo necesito hacer y qué ofrece ya HMR?
Aquí hay un pequeño ejemplo: https://webpack.js.org/guides/hot-module-replacement/
Un módulo sólo se puede actualizar si lo "aceptas". Por lo tanto, necesita module.hot.accept
el módulo en los padres o en los padres de los padres... por ejemplo, un enrutador es un buen lugar o una subvista.
Si solo desea usarlo con webpack-dev-server, simplemente agréguelo webpack/hot/dev-server
como punto de entrada. De lo contrario, necesitará algún código de administración de HMR que llame check
a y 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.
- Puedes usarlo para una parte de tu aplicación y no afecta a otros módulos.
- Si HMR está deshabilitado, el compilador elimina todo el código HMR (envuélvalo en
if(module.hot)
).
Advertencias
- Es experimental y no se ha probado tan bien.
- Espere algunos errores.
- Teóricamente utilizable en producción, pero puede que sea demasiado pronto para usarlo para algo serio.
- Es necesario realizar un seguimiento de los ID de los módulos entre compilaciones, por lo que es necesario almacenarlos (
records
). - El optimizador ya no puede optimizar los ID de los módulos después de la primera compilación. Un pequeño impacto en el tamaño del paquete.
- El código de tiempo de ejecución de HMR aumenta el tamaño del paquete.
- Para uso en producción, se requieren pruebas adicionales para probar los controladores HMR. Esto podría resultar bastante difícil.
Aunque la respuesta aceptada explica todo correctamente, la siguiente descripción debería ayudar a comprender más rápidamente qué es HMR.
Esencialmente (¡en pocas palabras!): ayuda al desarrollo al reducir la cantidad de actualizaciones de páginas al reemplazar los módulos con cambios en tiempo de ejecución.
Mientras buscaba sobre HMR encontré un artículo que explica el concepto pero es bastante largo así que aquí hay una imagen GIF que explica el concepto sin muchas palabras.
Aquí está en funcionamiento: observe que el temporizador no se reinicia a 0 como lo haría después de recargar la página, y CSS también cambia la actualización automática.
Webpack ayuda a lograr HMR. Puedes encontrar documentos aquí.
Ayuda a lograr lo siguiente:
Conservar el estado de la aplicación durante la recarga (que siempre se pierde sin HMR)
Ahorre un valioso tiempo de desarrollo actualizando únicamente lo que ha cambiado.
Modifique el estilo más rápido, casi comparable a cambiar estilos en el depurador del navegador.
Aquí está la guía del paquete web para lograr HMR