Trouver la bonne façon de séparer le contenu d'un site Web à l'aide de Webpack

Trouver la meilleure façon d'organiser le matériel d'un projet Web peut être une tâche ardue. Il existe de nombreux scénarios différents permettant aux utilisateurs de travailler avec des projets, de nombreuses technologies et d'autres facteurs qui doivent être pris en compte.

L'auteur du matériel, dont nous publions la traduction aujourd'hui, dit qu'il veut dire ici tout ce que vous devez savoir pour la préparation compétente du matériel de projet Web pour le travail. Premièrement, il s'agira de choisir une stratégie de séparation des fichiers de site la mieux adaptée à un projet particulier et à ses utilisateurs. Deuxièmement, les moyens de mettre en œuvre la stratégie choisie seront examinés.

image

Informations générales


Selon le glossaire Webpack , il existe deux stratégies de partage de fichiers. Il s'agit du fractionnement de bundle et du fractionnement de code. Ces termes peuvent sembler être utilisés de manière interchangeable, mais ils ne le sont pas.

  • Le fractionnement d'un bundle est une technique pour diviser de gros bundles en plusieurs parties, qui sont des fichiers plus petits. Ces fichiers, dans tous les cas, comme lorsque vous travaillez avec un seul bundle, seront téléchargés par tous les utilisateurs du site. La force de cette technique est d'améliorer l'utilisation des mécanismes de mise en cache basés sur un navigateur.
  • La séparation de code est une approche qui implique de charger dynamiquement le code selon les besoins. Cela conduit au fait que l'utilisateur ne télécharge que le code dont il a besoin pour travailler avec une certaine partie du site à un certain moment.

Le fractionnement de code semble être beaucoup plus intéressant que le fractionnement de code. Et, en fait, on a le sentiment que dans de nombreux articles sur notre sujet, l'accent est mis sur la séparation du code, cette technique est considérée comme le seul moyen intéressant d'optimiser les matériaux du site.

Cependant, je voudrais dire que pour de nombreux sites, c'est la première stratégie qui a beaucoup plus de valeur - la séparation des bundles. Et, peut-être, littéralement, tous les projets Web peuvent gagner à sa mise en œuvre.

Parlons de cela plus en détail.

Séparation des faisceaux


La technique de fractionnement des faisceaux est basée sur une idée très simple. Si vous avez un gros fichier et que vous y changez une seule ligne de code, l'utilisateur régulier devra télécharger l'intégralité du fichier lors de sa prochaine visite sur le site. Cependant, si vous divisez ce fichier en deux fichiers, le même utilisateur devra télécharger uniquement celui qui a été modifié et le deuxième fichier sera extrait du cache du navigateur.

Il convient de noter que, puisque l'optimisation des matériaux du site en fractionnant les bundles est liée à la mise en cache, les utilisateurs visitant le site pour la première fois devront de toute façon télécharger tous les matériaux, donc cela ne fait aucune différence pour eux que ces matériaux soient présentés sous la forme d'un fichier unique ou de plusieurs .

Il me semble que trop de discussions sur la performance des projets web sont dédiées aux utilisateurs qui visitent le site pour la première fois. C'est peut-être le cas, en partie à cause de l'importance de la première impression que le projet va donner à l'utilisateur, ainsi que du fait que la quantité de données transmises aux utilisateurs lors de leur première visite sur le site est simple et pratique à mesurer.

En ce qui concerne les visiteurs réguliers, il peut être difficile de mesurer l'impact des techniques d'optimisation des matériaux qui leur sont appliquées. Mais nous devons simplement connaître les conséquences de telles optimisations.

Pour analyser ces choses, vous avez besoin de quelque chose comme une feuille de calcul. Vous devrez également créer une liste stricte de conditions dans lesquelles nous pouvons tester chacune des stratégies de mise en cache étudiées.

Voici un script qui correspond à la description générale donnée dans le paragraphe précédent:

  • Alice visite notre site une fois par semaine pendant 10 semaines.
  • Nous mettons à jour le site une fois par semaine.
  • Chaque semaine, nous mettons à jour la page de liste des produits.
  • De plus, nous avons une page avec les détails du produit, mais nous n'y travaillons pas encore.
  • Au cours de la cinquième semaine, nous ajoutons un nouveau package npm aux documents du projet.
  • Au cours de la huitième semaine, nous mettons à jour l'un des packages npm déjà utilisés dans le projet.

Il y a des gens (comme moi) qui essaieront de rendre un tel scénario aussi réaliste que possible. Mais vous n'avez pas besoin de faire ça. Le vrai scénario ici n'a pas vraiment d'importance. Pourquoi en est-il ainsi - nous le saurons bientôt.

▍ Conditions initiales


Supposons que la taille totale de notre package JavaScript soit considérable de 400 Ko et que, dans les conditions actuelles, nous transférons tout cela à l'utilisateur sous la forme d'un seul fichier main.js Nous avons une configuration Webpack, qui, en termes généraux, est similaire à la suivante (j'ai supprimé les choses qui ne sont pas pertinentes pour notre conversation):

 const path = require('path'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, }; 

Webpack nomme le fichier main.js résultant lorsqu'il existe une seule entrée dans la configuration.

Si vous n'avez pas une très bonne idée de travailler avec le cache, gardez à l'esprit que chaque fois que j'écris main.js ici, je veux dire quelque chose comme main.xMePWxHo.js . Une séquence de caractères fous est un hachage du contenu d'un fichier, ce qu'on appelle contenthash dans la configuration. L'utilisation de cette approche conduit au fait que, lors du changement de code, les noms de fichiers changent également, ce qui oblige le navigateur à télécharger de nouveaux fichiers.

Conformément au scénario ci-dessus, lorsque nous contenthash des modifications au code du site chaque semaine, la ligne contenthash du package change. En conséquence, visitant chaque semaine notre site, Alice est obligée de télécharger un nouveau fichier de 400 Ko.

Si nous fabriquons une belle tablette (avec une ligne de résultat inutile jusqu'à présent) contenant des données sur le volume hebdomadaire de chargement de données par ce fichier, alors nous obtenons ce qui suit.


La quantité de données téléchargées par l'utilisateur

En conséquence, il apparaît que l'utilisateur, en 10 semaines, a téléchargé 4,12 Mo de code. Cet indicateur peut être amélioré.

▍Séparation des packages tiers du code principal


Divisez le grand emballage en deux parties. Notre propre code sera dans le fichier main.js et le code tiers dans le fichier vendor.js . C'est facile à faire, la configuration Webpack suivante nous aidera avec ceci:

 const path = require('path'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, optimization: {   splitChunks: {     chunks: 'all',   }, }, }; 

Webpack 4 essaie de rendre la vie aussi simple que possible pour le développeur, il fait donc tout ce qu'il peut et ne lui demande pas de savoir exactement comment diviser les bundles en parties.

Ce type de comportement automatique du programme conduit à quelques délices, tels que: "Eh bien, quel charme ce Webpack est", et à de nombreuses questions dans l'esprit: "Qu'est-ce que cela fait avec mes bundles?".

Dans tous les cas, l'ajout d' optimization.splitChunks.chunks = 'all' à la configuration de configuration indique à Webpack que nous en avons besoin pour tout prendre dans node_modules et le mettre dans le vendors~main.js

Après avoir fait une telle séparation de base du bundle, Alice, qui visite régulièrement notre site chaque semaine, téléchargera le fichier main.js de 200 Ko à chaque fois qu'elle visite. Mais elle ne téléchargera le fichier vendor.js que trois fois. Cela se produira lors des visites des première, cinquième et huitième semaines. Voici le tableau correspondant, dans lequel, par la volonté du destin, les tailles des vendor.js main.js et vendor.js au cours des quatre premières semaines coïncident et sont égales à 200 Ko.


La quantité de données téléchargées par l'utilisateur

En conséquence, il s'avère que la quantité de données téléchargées par l'utilisateur sur 10 semaines était de 2,64 Mo. Autrement dit, par rapport à ce qui était avant la séparation du faisceau, le volume a diminué de 36%. Pas un si mauvais résultat obtenu en ajoutant quelques lignes au fichier de configuration. Soit dit en passant, avant de poursuivre la lecture - faites de même dans votre projet. Et si vous avez besoin de passer de Webpack 3 à 4 - faites-le et ne vous inquiétez pas, car le processus est assez simple et toujours gratuit.

Il me semble que l'amélioration considérée ici semble quelque peu abstraite, puisqu'elle s'étale sur 10 semaines. Cependant, si l'on considère la quantité de données envoyées à un utilisateur fidèle, il s'agit d'une réduction honnête de ce volume de 36%. C'est un très bon résultat, mais il peut être amélioré.

▍ Mettez en surbrillance les packages dans des fichiers séparés


Le fichier vendor.js souffre du même problème que l'original main.js Il consiste en ce que la modification de tout package inclus dans ce fichier oblige un utilisateur régulier à télécharger à nouveau l'intégralité du fichier.

Pourquoi ne créons-nous pas des fichiers séparés pour chaque paquet npm? Ce n'est pas difficile à faire, alors décomposons notre react , lodash , redux , moment , etc. dans des fichiers séparés. La configuration Webpack suivante nous aidera avec ceci:

 const path = require('path'); const webpack = require('webpack'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), plugins: [   new webpack.HashedModuleIdsPlugin(), //        ], output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, optimization: {   runtimeChunk: 'single',   splitChunks: {     chunks: 'all',     maxInitialRequests: Infinity,     minSize: 0,     cacheGroups: {       vendor: {         test: /[\\/]node_modules[\\/]/,         name(module) {           //  ,   node_modules/packageName/not/this/part.js           //  node_modules/packageName           const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];           //  npm- ,   ,           //  URL,        @           return `npm.${packageName.replace('@', '')}`;         },       },     },   }, }, }; 

Dans la documentation, vous pouvez trouver une excellente explication des constructions utilisées ici, mais je consacre encore un peu de temps à raconter certaines choses, car il m'a fallu beaucoup de temps pour les utiliser correctement.

  • Webpack a des installations standard tout à fait raisonnables, qui, en fait, ne sont pas si raisonnables. Par exemple, le nombre maximal de fichiers de sortie est défini sur 3, la taille de fichier minimale est de 30 Ko (c'est-à-dire que les fichiers plus petits seront fusionnés). Je l'ai redéfini.
  • cacheGroups est l'endroit où nous définissons les règles de regroupement des données par Webpack dans les fichiers de sortie. J'ai un groupe ici, vendor , qui sera utilisé pour tout module chargé à partir de node_modules . Habituellement, le nom du fichier de sortie est donné sous forme de chaîne. Mais j'ai donné un name tant que fonction qui sera appelée pour chaque fichier traité. Ensuite, je prends le nom du package dans le chemin du module. En conséquence, nous obtenons un fichier pour chaque package. Par exemple, npm.react-dom.899sadfhj4.js .
  • Les noms de package, afin qu'ils puissent être publiés dans npm, doivent être adaptés à une utilisation dans les URL , nous n'avons donc pas besoin d'effectuer l'opération encodeURI sur les noms de packageName . Cependant, je suis tombé sur un problème que le serveur .NET refuse de travailler avec des fichiers qui ont le symbole @ dans leurs noms (ces noms sont utilisés pour les packages avec une portée de nom donnée, les soi-disant packages de portée), donc moi, dans le correspondant fragment de code, je me débarrasse de ces caractères.

La configuration ci-dessus de Webpack est bonne en ce sens que vous pouvez la configurer une fois, puis l'oublier. Il ne nécessite pas de faire référence à des packages spécifiques par leur nom.Par conséquent, après sa création, il reste pertinent, même lors de la modification de la composition des packages.

Alice, notre visiteur régulier, main.js toujours main.js 200 kilo-octets chaque semaine, et la première fois qu'elle visite le site, elle doit télécharger 200 Ko de packages npm, mais elle n'a pas à télécharger les mêmes packages deux fois.

Vous trouverez ci-dessous une nouvelle version du tableau avec des informations sur le volume de téléchargements de données hebdomadaires. Par une étrange coïncidence, la taille de chaque fichier avec les packages npm est de 20 Ko.


La quantité de données téléchargées par l'utilisateur

Maintenant, le volume de données téléchargées en 10 semaines est de 2,24 Mo. Cela signifie que nous avons amélioré le taux de base de 44%. Le résultat est déjà très décent, mais la question se pose de savoir s'il est possible de le faire pour obtenir un résultat supérieur à 50%. Si cela se produit, ce sera tout simplement génial.

▍ Division du code d'application en fragments


Nous revenons au fichier main.js , que la malheureuse Alice doit constamment télécharger.

Comme je l'ai dit ci-dessus, il y a deux sections distinctes sur notre site Web. Le premier est une liste de produits, le second est une page avec des informations détaillées sur le produit. La taille du code, unique pour chacun d'eux, est de 25 Ko (et 150 Ko de code sont utilisés à la fois là et là).

La page d'information sur le produit n'est pas sujette à changement, comme nous l'avons déjà perfectionnée. Par conséquent, si nous extrayons son code dans un fichier séparé, ce fichier, la plupart du temps utilisé avec le site, sera téléchargé dans le navigateur depuis le cache.

De plus, il s'est avéré que nous avons un énorme fichier SVG intégré utilisé pour le rendu des icônes, qui pèse jusqu'à 25 Ko et change rarement.

Il faut faire quelque chose avec ça.

Nous avons créé manuellement plusieurs points d'entrée, indiquant à Webpack qu'il devait créer un fichier distinct pour chacune de ces entités.

 module.exports = { entry: {   main: path.resolve(__dirname, 'src/index.js'),   ProductList: path.resolve(__dirname, 'src/ProductList/ProductList.js'),   ProductPage: path.resolve(__dirname, 'src/ProductPage/ProductPage.js'),   Icon: path.resolve(__dirname, 'src/Icon/Icon.js'), }, output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash:8].js', }, plugins: [   new webpack.HashedModuleIdsPlugin(), //        ], optimization: {   runtimeChunk: 'single',   splitChunks: {     chunks: 'all',     maxInitialRequests: Infinity,     minSize: 0,     cacheGroups: {       vendor: {         test: /[\\/]node_modules[\\/]/,         name(module) {           //  ,   node_modules/packageName/not/this/part.js           //  node_modules/packageName           const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];           //  npm- ,   ,           //  URL,        @           return `npm.${packageName.replace('@', '')}`;         },       },     },   }, }, }; 

Le Webpack, qui travaille dur, créera en outre des fichiers pour ce qui est courant, par exemple, ProductList et ProductPage , c'est-à-dire qu'il n'y aura pas de code en double.

Ce que nous venons de faire permettra à Alice d'économiser 50 Ko de trafic presque chaque semaine. Veuillez noter que nous avons modifié le fichier de description des icônes au cours de la sixième semaine. Voici notre table traditionnelle.


La quantité de données téléchargées par l'utilisateur

Maintenant, en seulement dix semaines, seulement 1,815 Mo de données ont été téléchargées. Cela signifie que les économies de trafic ont été impressionnantes de 56%. Conformément à notre scénario théorique, un utilisateur régulier travaillera toujours avec ce niveau d'économies.

Tout cela est dû aux modifications apportées à la configuration de Webpack. Nous n'avons pas modifié le code d'application pour obtenir de tels résultats.

Plus tôt, j'ai parlé du fait que le scénario spécifique dans lequel un tel test est effectué, en fait, ne joue pas un rôle spécial. Cela est dû au fait que, quel que soit le scénario utilisé, la conclusion de tout ce dont nous avons parlé sera la même: la division de l'application en petits fichiers qui ont du sens lorsqu'elle est appliquée à son architecture nous permet de réduire le volume des données du site, chargé par ses utilisateurs réguliers.

Nous allons bientôt commencer à parler de séparation de code, mais je voudrais d'abord répondre à trois questions auxquelles vous pensez probablement maintenant.

▍ Question numéro 1. La nécessité d'effectuer de nombreuses requêtes ne nuit-elle pas à la vitesse de chargement du site?


Vous pouvez donner une réponse courte et simple à cette question: "Non, cela ne fait pas de mal." Une situation similaire a entraîné un problème dans le passé, lorsque le protocole HTTP / 1.1 était utilisé, et lors de l'utilisation de HTTP / 2, ce n'est plus pertinent.

Cependant, il convient de noter que dans cet article, publié en 2016, et dans cet article de la Khan Academy 2015, les conclusions sont tirées que même en utilisant HTTP / 2, l'utilisation d'un trop grand nombre de fichiers ralentit le téléchargement. Mais dans ces deux matériaux, «trop» signifie «plusieurs centaines». Par conséquent, il convient de se rappeler que si vous devez travailler avec des centaines de fichiers, les restrictions sur le traitement parallèle des données peuvent affecter leur vitesse de téléchargement.

Si vous êtes intéressé, la prise en charge HTTP / 2 est disponible dans IE 11 sur Windows 10. De plus, j'ai fait une étude complète parmi ceux qui utilisent des systèmes plus anciens. Ils ont déclaré à l'unanimité que la vitesse de chargement de leur site Web n'était pas particulièrement préoccupante.

▍ Question numéro 2. Les bundles Webpack ont ​​un code d'assistance. Cela crée-t-il une charge supplémentaire sur le système?


Oui.

▍ Question numéro 3. Lorsque vous travaillez avec de nombreux petits fichiers, leur niveau de compression se détériore, non?


Oui, c'est également vrai. En fait, je voudrais dire ceci:

  • Plus de fichiers signifie plus de code d'assistance Webpack.
  • Plus de fichiers signifie moins de compression.

Voyons cela pour comprendre à quel point c'est mauvais.

Je viens d'effectuer un test dans lequel le code d'un fichier de 190 Ko a été divisé en 19 parties. Cela a ajouté environ 2% à la quantité de données envoyées au navigateur.

En conséquence, il s'avère que lors de la première visite sur le site, l'utilisateur téléchargera 2% de données en plus, et lors des visites suivantes - 60% de moins, et cela continuera pendant très, très longtemps.
Cela vaut-il la peine de s'inquiéter? Non, ça n'en vaut pas la peine.

Lorsque j'ai comparé un système utilisant 1 fichier et un système avec 19 fichiers, je l'ai testé en utilisant différents protocoles, dont HTTP / 1.1. Le tableau ci-dessous soutient fortement l'idée qu'avoir plus de fichiers signifie mieux.


Données sur l'utilisation de 2 versions d'un site hébergé sur un hébergement statique Firebase, dont le code mesure 190 Ko, mais, dans le premier cas, il est regroupé dans 1 fichier et dans le second, il est divisé en 19

Lorsque vous travaillez dans des réseaux 3G et 4G, le téléchargement d'un site avec 19 fichiers a pris 30% moins de temps que le téléchargement d'un site avec un fichier.

Il y a beaucoup de bruit dans les données présentées dans le tableau. Par exemple, une session de téléchargement d'un site par 4G (Exécution 2 dans le tableau) a pris 646 ms, une autre (Exécution 4) - 1116 ms, ce qui est 73% plus long. Par conséquent, il y a un sentiment que dire que HTTP / 2 est "30% plus rapide" est quelque peu malhonnête.

J'ai créé ce tableau afin de voir ce que donne l'utilisation de HTTP / 2. Mais, en fait, la seule chose que l'on puisse dire ici, c'est que l'utilisation de HTTP / 2 n'affecte probablement pas particulièrement le chargement des pages.

Les deux dernières lignes de ce tableau ont été une véritable surprise. Voici les résultats pour pas la dernière version de Windows avec IE11 et HTTP / 1.1. Si j'essayais de prédire les résultats du test à l'avance, je dirais certainement qu'une telle configuration chargerait les matériaux beaucoup plus lentement que les autres. Certes, une connexion réseau très rapide a été utilisée ici, et moi, pour de tels tests, je devrais probablement utiliser quelque chose de plus lent.

Et maintenant je vais vous raconter une histoire. Pour explorer mon site sur un système très ancien, j'ai téléchargé la machine virtuelle Windows 7 depuis le site Web de Microsoft. IE8 y était installé, que j'ai décidé de mettre à niveau vers IE9. Pour ce faire, je suis allé sur la page Microsoft conçue pour télécharger IE 9. Mais je n'ai pas pu le faire.


Cette malchance ...

Soit dit en passant, si nous parlons de HTTP / 2, je tiens à noter que ce protocole est intégré dans Node.js. Si vous voulez expérimenter, vous pouvez utiliser le petit serveur HTTP / 2 que j'ai écrit avec le support du cache de réponse, gzip et brotli.

Peut-être, j'ai dit tout ce que je voulais sur la méthode de séparation des faisceaux. Je pense que le seul inconvénient de cette approche, lors de l'utilisation de laquelle les utilisateurs doivent télécharger un grand nombre de fichiers, en fait, n'est pas un tel «inconvénient».

Parlons maintenant de la séparation du code.

Séparation de code


L'idée principale de la technique de fractionnement de code est: "Ne téléchargez pas de code inutile." On m'a dit que l'utilisation de cette approche n'a de sens que pour certains sites.

Je préfère, en ce qui concerne la séparation de code, utiliser la règle 20/20 que je viens de formuler. S'il y a une partie du site qui n'est visitée que par 20% des utilisateurs, et que sa fonctionnalité est fournie par plus de 20% du code JavaScript du site, alors ce code doit être téléchargé uniquement sur demande.

Bien entendu, ces chiffres ne sont pas absolus, ils peuvent être ajustés à une situation spécifique et, en réalité, il existe des scénarios beaucoup plus complexes que celui décrit ci-dessus. La chose la plus importante ici est l'équilibre, et il est tout à fait normal de ne pas utiliser du tout la séparation de code, si cela n'a aucun sens pour votre site.

▍ Séparé ou non?


Comment trouver la réponse à la question de savoir si vous avez besoin d'une séparation de code ou non? Supposons que vous ayez une boutique en ligne et que vous envisagiez de séparer du reste du code le code utilisé pour recevoir le paiement des clients, car seulement 30% des visiteurs achètent quelque chose chez vous.

Que puis-je dire? Tout d'abord, vous devez travailler à remplir le magasin et à vendre quelque chose qui serait intéressant pour plus de visiteurs du site. Deuxièmement, vous devez comprendre combien de code est complètement unique pour la section du site où le paiement est accepté. Étant donné que vous devriez toujours faire un «fractionnement de bundle» avant le «fractionnement de code», et vous l'espérez, vous savez probablement déjà de quelles tailles le code nous intéresse.

Peut-être que ce code peut s'avérer plus petit que vous ne le pensez, donc avant de vous réjouir de la nouvelle opportunité d'optimiser votre site, vous devez tout calculer en toute sécurité. Si vous, par exemple, avez un site React, alors le référentiel, les réducteurs, le système de routage, les actions seront partagés par toutes les parties du site. Unique pour différentes parties du code du site sera principalement représenté par des composants et des fonctions auxiliaires pour eux.

Ainsi, vous avez découvert qu'un code complètement unique de la section du site utilisée pour payer les achats prend 7 Ko. La taille du reste du code du site est de 300 Ko. Dans une telle situation, je ne m'engagerais pas dans la séparation de code pour plusieurs raisons:

  • Si vous téléchargez ces 7 Ko à l'avance, le site ne ralentira pas. N'oubliez pas que les fichiers sont téléchargés en parallèle et essayez de mesurer la différence nécessaire pour télécharger 300 Ko et 307 Ko de code.
  • Si vous téléchargez ce code plus tard, l'utilisateur devra attendre après avoir cliqué sur le bouton "Payer". Et c'est le moment même où vous avez besoin de tout pour que tout se passe le mieux possible.
  • La séparation du code nécessite des modifications de l'application. Dans le code, là où tout a été fait de manière synchrone auparavant, la logique asynchrone apparaît. , , , , , .

, , , .

.


, , , .

. , . :

 require('whatwg-fetch'); require('intl'); require('url-polyfill'); require('core-js/web/dom-collections'); require('core-js/es6/map'); require('core-js/es6/string'); require('core-js/es6/array'); require('core-js/es6/object'); 

index.js , :

 import './polyfills'; import React from 'react'; import ReactDOM from 'react-dom'; import App from './App/App'; import './index.css'; const render = () => { ReactDOM.render(<App />, document.getElementById('root')); } render(); // ,      

Webpack , , npm-. 25 , 90% , .

Webpack 4 import() ( import ), :

 import React from 'react'; import ReactDOM from 'react-dom'; import App from './App/App'; import './index.css'; const render = () => { ReactDOM.render(<App />, document.getElementById('root')); } if ( 'fetch' in window && 'Intl' in window && 'URL' in window && 'Map' in window && 'forEach' in NodeList.prototype && 'startsWith' in String.prototype && 'endsWith' in String.prototype && 'includes' in String.prototype && 'includes' in Array.prototype && 'assign' in Object && 'entries' in Object && 'keys' in Object ) { render(); } else { import('./polyfills').then(render); } 

, , , — . — render() . , Webpack npm-, , render() .

, import() Babel dynamic-import . , Webpack, import() , .

, . .

▍ React,


. , , , .

, npm- . , , 100 .

, , URL /admin , <AdminPage> . Webpack , import AdminPage from './AdminPage.js' .

. , , import('./AdminPage.js') , Webpack , .

, .

, , AdminPage , , URL /admin . , :

 import React from 'react'; class AdminPageLoader extends React.PureComponent { constructor(props) {   super(props);   this.state = {     AdminPage: null,   } } componentDidMount() {   import('./AdminPage').then(module => {     this.setState({ AdminPage: module.default });   }); } render() {   const { AdminPage } = this.state;   return AdminPage     ? <AdminPage {...this.props} />     : <div>Loading...</div>; } } export default AdminPageLoader; 

. (, URL /admin ), ./AdminPage.js , .

render() , <AdminPage> , <div>Loading...</div> , <AdminPage> , .

, react-loadable , React .

Résumé


, , (, , CSS). :

  • — .
  • , — .

Chers lecteurs! ?

Source: https://habr.com/ru/post/fr423483/


All Articles