Qu'est-ce que le remplacement de module à chaud dans Webpack?

245

J'ai lu quelques pages sur le remplacement de module à chaud dans Webpack.
Il existe même un exemple d'application qui l' utilise .

J'ai lu tout cela et je n'ai toujours pas compris l'idée.

Que puis-je en faire?

  1. Est-il censé être utilisé uniquement en développement et non en production?
  2. Est-ce comme LiveReload, mais vous devez le gérer vous-même?
  3. WebpackDevServer est-il intégré à LiveReload d'une manière ou d'une autre?

Supposons que je veuille mettre à jour mes modules CSS (une feuille de style) et JS lorsque je les enregistre sur le disque, sans recharger la page et sans utiliser de plugins tels que LiveReload. Est-ce quelque chose que le remplacement de module à chaud peut m'aider? Quel type de travail dois-je faire et que fournit déjà HMR?

Dan Abramov
la source
HMR avec Webpack est presque aussi bon que cela: medium.com/@the1mills/…
Alexander Mills

Réponses:

408

Je veux d'abord noter que le remplacement de module à chaud (HMR) est toujours une fonctionnalité expérimentale.

HMR est un moyen d'échanger des modules dans une application en cours d'exécution (et d'ajouter / supprimer des modules). Vous pouvez essentiellement mettre à jour les modules modifiés sans recharger une page entière.

Documentation

Pré-requis:

Ce n'est pas tant pour HMR, mais voici les liens:

J'ajouterai ces réponses à la documentation.

Comment ça marche?

Depuis la vue de l'application

Le code d'application demande au runtime HMR de vérifier les mises à jour. Le runtime HMR télécharge les mises à jour (async) et indique au code de l'application qu'une mise à jour est disponible. Le code d'application demande au runtime HMR d'appliquer les mises à jour. Le runtime HMR applique les mises à jour (synchronisation). Le code d'application peut ou non nécessiter une interaction de l'utilisateur dans ce processus (vous décidez).

Depuis la vue du compilateur (webpack)

En plus des actifs normaux, le compilateur doit émettre la «mise à jour» pour permettre la mise à jour d'une version précédente vers cette version. La "mise à jour" comprend deux parties:

  1. le manifeste de mise à jour (json)
  2. un ou plusieurs morceaux de mise à jour (js)

Le manifeste contient le nouveau hachage de compilation et une liste de tous les morceaux de mise à jour (2).

Les blocs de mise à jour contiennent du code pour tous les modules mis à jour dans ce bloc (ou un indicateur si un module a été supprimé).

Le compilateur s'assure en outre que les identifiants de module et de bloc sont cohérents entre ces builds. Il utilise un fichier json "records" pour les stocker entre les builds (ou il les stocke en mémoire).

Depuis la vue du module

HMR est une fonctionnalité opt-in, elle n'affecte donc que les modules contenant du code HMR. La documentation décrit l'API disponible dans les modules. En général, le développeur de module écrit des gestionnaires qui sont appelés lorsqu'une dépendance de ce module est mise à jour. Ils peuvent également écrire un gestionnaire qui est appelé lorsque ce module est mis à jour.

Dans la plupart des cas, il n'est pas obligatoire d'écrire du code HMR dans chaque module. Si un module n'a pas de gestionnaires HMR, la mise à jour bouillonne. Cela signifie qu'un seul gestionnaire peut gérer les mises à jour pour une arborescence de modules complète. Si un seul module de cette arborescence est mis à jour, l'arborescence complète des modules est rechargée (uniquement rechargée, pas transférée).

Depuis la vue d'exécution HMR (technique)

Un code supplémentaire est émis pour l'exécution du système du module pour suivre le module parentset children.

Côté gestion, le runtime prend en charge deux méthodes: checket apply.

A checkfait une requête HTTP au manifeste de mise à jour. Lorsque cette demande échoue, aucune mise à jour n'est disponible. Sinon, la liste des morceaux mis à jour est comparée à la liste des morceaux actuellement chargés. Pour chaque bloc chargé, le bloc de mise à jour correspondant est téléchargé. Toutes les mises à jour du module sont stockées dans le runtime en tant que mises à jour. Le runtime passe à l' readyétat, ce qui signifie qu'une mise à jour a été téléchargée et est prête à être appliquée.

Pour chaque nouvelle demande de bloc à l'état prêt, le bloc de mise à jour est également téléchargé.

La applyméthode marque tous les modules mis à jour comme non valides. Pour chaque module non valide, il doit y avoir un gestionnaire de mise à jour dans le module ou des gestionnaires de mise à jour dans chaque parent. Sinon, les bulles invalides apparaissent et marque tous les parents comme invalides également. Ce processus se poursuit jusqu'à ce qu'il n'y ait plus de «bulle». S'il bouillonne jusqu'à un point d'entrée, le processus échoue.

Maintenant, tous les modules invalides sont éliminés (gestionnaire d'élimination) et déchargés. Ensuite, le hachage actuel est mis à jour et tous les gestionnaires "acceptent" sont appelés. Le runtime revient à l' idleétat et tout se poursuit normalement.

morceaux de mise à jour générés

Que puis-je en faire?

Vous pouvez l'utiliser en développement en remplacement de LiveReload. En fait, le webpack-dev-server prend en charge un mode à chaud qui essaie de mettre à jour avec HMR avant d'essayer de recharger la page entière. Il vous suffit d'ajouter le webpack/hot/dev-serverpoint d'entrée et d'appeler le serveur de développement avec --hot.

Vous pouvez également l'utiliser en production comme mécanismes de mise à jour. Ici, vous devez écrire votre propre code de gestion qui intègre HMR à votre application.

Certains chargeurs génèrent déjà des modules pouvant être mis à jour à chaud. Par exemple, le style-loaderpeut échanger la feuille de style. Vous n'avez rien à faire de spécial.

Supposons que je veuille mettre à jour mes modules CSS (une feuille de style) et JS lorsque je les enregistre sur le disque, sans recharger la page et sans utiliser de plugins tels que LiveReload. Est-ce quelque chose que le remplacement de module à chaud peut m'aider?

Oui

Quel type de travail dois-je faire et que fournit déjà HMR?

Voici un petit exemple: https://webpack.js.org/guides/hot-module-replacement/

Un module ne peut être mis à jour que si vous "l'acceptez". Vous devez donc module.hot.acceptle module dans les parents ou les parents des parents ... par exemple, un routeur est un bon endroit, ou une sous-vue.

Si vous voulez seulement l'utiliser avec le serveur webpack-dev-server, ajoutez simplement webpack/hot/dev-servercomme point d'entrée. Sinon, vous avez besoin d'un code de gestion HMR qui appelle checket apply.

Opinion: Qu'est-ce qui le rend si cool?

  • C'est LiveReload mais pour chaque type de module.
  • Vous pouvez l'utiliser en production.
  • Les mises à jour respectent votre fractionnement de code et téléchargent uniquement les mises à jour pour les parties utilisées de votre application.
  • Vous pouvez l'utiliser pour une partie de votre application et cela n'affecte pas les autres modules
  • Si HMR est désactivé, tout le code HMR est supprimé par le compilateur (enveloppez-le if(module.hot)).

Avertissements

  • C'est expérimental et pas si bien testé.
  • Attendez-vous à quelques bugs.
  • Théoriquement utilisable en production, mais il est peut-être trop tôt pour l'utiliser pour quelque chose de grave.
  • Les ID de module doivent être suivis entre les compilations, vous devez donc les stocker ( records).
  • L'optimiseur ne peut plus optimiser les ID de module après la première compilation. Un peu d'impact sur la taille du bundle.
  • Le code d'exécution HMR augmente la taille du bundle.
  • Pour une utilisation en production, des tests supplémentaires sont nécessaires pour tester les gestionnaires HMR. Cela pourrait être assez difficile.
Tobias K.
la source
146
Une sacrée réponse.
Dan Abramov
13
Merci encore pour l'explication, j'ai fait une vidéo montrant la puissance de HMR pour éditer en direct une application React.
Dan Abramov
1
plutôt cool ... J'ai pensé à faire un chargeur de réaction qui ajoute du chargement HMR et asynchrone aux composants réactifs.
Tobias K.
4
J'ai copié cette réponse dans la documentation: webpack.github.io/docs/hot-module-replacement-with-webpack.html
Tobias K.
2
Vous pouvez intercepter des erreurs dans les modules mis à jour lorsque vous encapsulez le requiregestionnaire de mise à jour HMR dans un bloc try-catch.
Tobias K.
10

La réponse acceptée développe tout ce qui est correct de toute façon, la description suivante aide à comprendre ce qu'est HMR rapidement.

Le remplacement à chaud du module est l'une des plus récentes techniques de développement javascript qui attire l'attention des développeurs. Il facilite le développement en réduisant le nombre d'actualisation des pages en remplaçant les modules par des modifications au moment de l'exécution.

En cherchant sur HMR, j'ai trouvé un article qui explique le concept sur Internet, vous pouvez l'obtenir à partir d'ici et ajouter une image GIF qui explique le concept sans trop d'explications.

Ici, c'est au travail - notez que le minuteur ne se réinitialise pas à 0 comme il le ferait après un rechargement de page, et css modifie également l'actualisation automatique. GIF de remplacement de module à chaud

Webpack aide à atteindre HMR. Vous pouvez trouver des documents ici

Il aide à atteindre les objectifs suivants

  • Conserver l'état de l'application perdu lors d'un rechargement complet.

  • Gagnez un temps de développement précieux en ne mettant à jour que ce qui a changé.

  • Ajustez le style plus rapidement - presque comparable au changement de style dans le débogueur du navigateur.

Voici le guide du webpack pour réaliser HMR

samuelj90
la source