Aujourd'hui, nous publions la deuxième partie de la traduction du matériel, qui est consacrée à l'utilisation des modules JS dans la production.

→ Au fait, voici la 
première partie de l' article.
Importation dynamique
L'un des inconvénients de l'utilisation d'expressions d'importation réelles pour séparer le code et charger les modules est que la tâche de travailler avec des navigateurs qui ne prennent pas en charge les modules incombe au développeur.
Et si vous souhaitez utiliser des commandes dynamiques 
import() pour organiser le chargement de code paresseux, vous devrez, entre autres, faire face au fait que certains navigateurs, bien que, très certainement, 
les modules de support , ne prennent toujours 
pas en charge les commandes dynamiques import () (Edge 16–18, Firefox 60–66, Safari 11, Chrome 61–63).
Heureusement, ce problème nous aidera à résoudre un 
polyfill petit (environ 400 octets) et extrĂŞmement rapide.
L'ajout de ce polyfill à un projet Web est très simple. Il vous suffit de l'importer et de l'initialiser au point d'entrée principal de l'application (avant d'appeler l'une des commandes 
import() du code):
 import dynamicImportPolyfill from 'dynamic-import-polyfill';  
Et la dernière chose à faire pour que ce schéma fonctionne, est de dire à Rollup qu'il doit renommer les commandes dynamic 
import() qui apparaissent dans le code en utilisant le nom que vous 
choisissez (via l'option 
output.dynamicImportFunction ). Un polyfill qui implémente la fonction d'importation dynamique utilise le nom 
__import__ par défaut, mais il peut être 
personnalisé .
La raison pour laquelle vous devez renommer 
import() expressions 
import() est que l' 
import est, en JavaScript, un mot-clé. Cela signifie qu'il est impossible, par polyfill, d'organiser le remplacement de la commande standard 
import() par une commande du mĂŞme nom. Si vous essayez de faire cela, une erreur de syntaxe se produira.
Mais c'est très bien que Rollup renomme les commandes lors de la construction du projet, car cela signifie que vous pouvez utiliser des commandes standard dans le code source. De plus, à l'avenir, lorsque le polyfill ne sera plus nécessaire, le code source du projet n'aura pas à être réécrit, changeant pour 
import ce qui était précédemment nommé d'une manière ou d'une autre.
Chargement efficace de JavaScript
Chaque fois que vous utilisez la séparation de code, cela ne fait pas de mal d'organiser le préchargement de tous les modules dont vous savez qu'ils seront chargés très prochainement (par exemple, ce sont tous les modules dans l'arborescence des dépendances du module principal, qui est le point d'entrée du projet).
Mais lorsque nous chargeons de vrais modules JavaScript (via 
<script type="module"> puis via les commandes d' 
import correspondantes), nous devons utiliser l'attribut 
modulepreload au lieu du 
préchargement habituel, qui est destiné uniquement aux scripts classiques.
 <link rel="modulepreload" href="/modules/main.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-one.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-two.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-three.XXXX.mjs"> <!-- ... --> <script type="module" src="/modules/main.XXXX.mjs"></script> 
En fait, la 
modulepreload est nettement meilleure que le mécanisme de 
preload traditionnel dans la précharge de vrais modules. Le fait est que lorsque vous l'utilisez, ce n'est pas seulement que le fichier est téléchargé. De plus, il démarre immédiatement, en dehors du thread principal, l'analyse et la compilation du script. Un 
preload régulier ne peut pas faire cela car il ne sait pas, lors du préchargement, si le fichier sera utilisé comme module ou comme script normal.
Cela signifie que le chargement des modules Ă  l'aide de l'attribut 
modulepreload souvent plus rapide et que lorsque les modules sont initialisés, il est moins susceptible de créer une charge excessive sur le thread principal, ce qui provoque des problèmes d'interface.
Création d'une liste de modules pour le préchargement
Le fragment d'entrée dans l'objet 
bundle Rollup contient une liste complète des importations dans leurs arborescences de dépendances statiques. Par conséquent, dans le hook Rollup 
generateBundle , il est facile d'obtenir une liste de fichiers qui doivent être préchargés.
Bien que des plugins puissent être trouvés dans npm pour générer des listes de préchargement de module, la création d'une liste similaire pour chaque point d'entrée dans l'arborescence des dépendances ne nécessite que quelques lignes de code. Par conséquent, je préfère créer ces listes manuellement, en utilisant quelque chose comme ce code:
 {  generateBundle(options, bundle) {     
Voici, par exemple, comment j'ai créé une 
liste de 
chargement de 
module pour 
philipwalton.com et pour mon 
application de démonstration , dont nous parlerons ci-dessous.
Veuillez noter que bien que l'attribut 
modulepreload nettement meilleur que le 
preload classique pour le chargement des scripts de module, il a la pire prise en charge du navigateur (actuellement, seul Chrome le prend en charge). Si une partie importante de votre trafic ne provient pas de Chrome, dans votre cas, il peut ĂŞtre judicieux d'utiliser la 
preload régulière au lieu de la 
preload du 
preload .
Concernant l'utilisation de la 
preload , je voudrais vous avertir de quelque chose. Le fait est que lors du chargement de scripts Ă  l'aide du 
preload , contrairement au 
modulepreload , ces scripts n'entrent pas dans la carte du module du navigateur. Cela signifie qu'il est possible que les demandes de préchargement puissent être exécutées plusieurs fois (par exemple, si le module importe le fichier avant que le navigateur ait fini de le précharger).
Pourquoi déployer de vrais modules en production?
Si vous utilisez déjà un bundler comme 
webpack , ainsi que si vous utilisez déjà le fractionnement de code et le préchargement des fichiers correspondants (similaire à ce que je viens de dire), alors vous vous demandez peut-être si vous devez passer à une stratégie concentré sur l'utilisation de vrais modules. Il y a plusieurs raisons qui me font croire que vous devriez envisager de passer aux modules. De plus, je pense qu'il est préférable de convertir un projet en modules réels que d'utiliser des scripts classiques avec leur propre code conçu pour charger des modules.
▍ Réduire la quantité totale de code
Si le projet utilise de vrais modules, les utilisateurs de navigateurs modernes n'auront pas à télécharger de code supplémentaire conçu pour charger des modules ou pour gérer les dépendances. Par exemple, lorsque vous utilisez de vrais modules, vous n'aurez pas besoin de charger 
les mécanismes d'exécution et le manifeste du webpack .
▍ Code de précharge amélioré
Comme mentionné dans la section précédente, l'utilisation de l'attribut 
modulepreload permet de charger du code, de l' 
modulepreload et de le compiler en dehors du thread principal. Tout le reste, par rapport Ă  l'attribut de 
preload , reste le même. Cela signifie que grâce au 
modulepreload pages deviennent interactives plus rapidement, et cela réduit la probabilité de bloquer le flux principal pendant l'interaction avec l'utilisateur.
Par conséquent, quelle que soit la taille du code d'application divisé en fragments, il sera beaucoup plus productif de télécharger ces fragments à l'aide des commandes d'importation et de l'attribut 
modulepreload que de les charger Ă  l'aide de la balise de 
script habituelle et de l'attribut de 
preload habituel (surtout si les balises correspondantes sont générées dynamiquement et ajouté au DOM lors de l'exécution).
En d'autres termes, un bundle de cumul de code de projet, composé de 20 fragments de module, se chargera plus rapidement qu'un bundle du même projet, composé de 20 fragments de script classiques préparés par webpack (non pas à cause de l'utilisation de webpack, mais parce que que ce ne sont pas de vrais modules).
▍ Améliorer l'orientation future du code
De nombreuses nouvelles fonctionnalités des navigateurs sont basées sur des modules et non sur des scripts classiques. Cela signifie que si vous prévoyez d'utiliser ces fonctionnalités, votre code doit être présenté sous la forme de vrais modules. Cela ne devrait pas être quelque chose de transpilé dans ES5 et chargé avec les moyens de la balise de 
script classique (c'est le problème que j'ai écrit lorsque j'ai essayé d'utiliser l' 
API expérimentale de 
stockage KV ).
Voici quelques-unes des nouvelles fonctionnalités de navigateur les plus intéressantes qui se concentrent exclusivement sur les modules:
Prise en charge du navigateur hérité
À l'échelle mondiale, 
plus de 83% des navigateurs prennent en charge les modules JavaScript (y compris l'importation dynamique), par conséquent, la plupart des utilisateurs pourront travailler avec un projet qui est passé à des modules sans aucun effort particulier de la part des développeurs de ce projet.
Dans le cas des navigateurs qui prennent en charge les modules mais ne prennent pas en charge l'importation dynamique, il est recommandé d'utiliser le 
polyfill dynamic-import-polyfill décrit ci-dessus. Puisqu'il est très petit et, si possible, utilise la méthode standard 
import() navigateur 
import() , l'utilisation de ce polyfill n'a presque aucun effet sur la taille ou les performances du projet.
Si nous parlons de navigateurs qui ne supportent absolument pas les modules, alors, pour organiser le travail avec eux, vous pouvez utiliser le 
modèle module / nomodule .
â–ŤExemple de fonctionnement
Puisqu'il est toujours plus facile de parler de compatibilité entre navigateurs que de la réaliser, j'ai créé une 
application de démonstration qui utilise les technologies décrites ci-dessus.
Cette application fonctionne dans les navigateurs comme Edge 18 et Firefox ESR, qui ne prennent pas en charge 
import() commandes d' 
import() dynamique 
import() . De plus, il fonctionne dans des navigateurs comme Internet Explorer 11, qui ne prennent pas en charge les modules.
Afin de montrer que la stratégie discutée ici convient non seulement aux projets simples, j'ai utilisé de nombreuses fonctionnalités dans cette application qui sont nécessaires aujourd'hui dans les grands projets:
- Transformation de code Ă  l'aide de Babel (y compris JSX).
- Dépendances CommonJS (par exemple react et react-dom).
- Dépendances CSS.
- Hachage de ressources
- Séparation de code
- Importation dynamique (avec un repli comme polyfill).
- Implémentation du modèle module / nomodule.
Le code du projet peut être trouvé sur 
GitHub (c'est-à-dire que vous pouvez bifurquer le référentiel et construire le projet vous-même), la version de démonstration est hébergée sur 
Glitch , ce qui vous permet de l'expérimenter.
La chose la plus importante dans le projet de démonstration est la 
configuration Rollup , car elle détermine la façon dont les modules résultants sont créés.
Résumé
J'espère que ce matériel vous a convaincu non seulement de la possibilité de déployer des modules JavaScript standard en production, mais aussi qu'il peut vraiment améliorer le temps de chargement du site et ses performances.
Voici un bref aperçu des étapes à suivre pour implémenter les modules dans le projet:
- Utilisez un bundler, parmi les formats de sortie pris en charge par lesquels il existe des modules ES2015.
- Approchez de manière agressive la séparation du code (si possible, jusqu'à l'allocation des dépendances de node_modulesen fragments séparés).
- Préchargez tous les modules qui se trouvent dans votre arborescence de dépendances statiques (en utilisant modulepreload).
- Utilisez polyfill pour les navigateurs qui ne prennent pas en charge import()instructionsimport()dynamiques.
- Utilisez le modèle de module / nomodule pour organiser le travail avec les navigateurs qui ne prennent pas en charge les modules.
Si vous utilisez déjà Rollup pour construire le projet, je voudrais que vous essayiez de ce dont je parlais ici et que vous alliez déployer de vrais modules en production (en utilisant des techniques de séparation de code et d'importation dynamique). Si vous le faites, 
faites-moi savoir comment vous allez. Je suis intéressé à connaître les problèmes et les cas réussis d'introduction de modules.
Il est très clair que les modules sont l’avenir de JavaScript. J'aimerais voir, et de préférence bientôt, comment les outils que nous utilisons et les bibliothèques auxiliaires adoptent cette technologie. J'espère que ce matériel pourra au moins aider un peu ce processus.
Chers lecteurs! Utilisez-vous des modules JS en production?
