Collecter le paquet de rĂŞves avec Webpack

Les applications, sites et autres ressources JS deviennent de plus en plus complexes et les outils de construction sont la réalité du développement Web. Les bundlers aident à emballer, compiler et organiser les bibliothèques. Webpack est l'un des outils open source puissants et flexibles qui peuvent être parfaitement personnalisés pour créer l'application client.

Maxim Sosnov ( crazymax11 ) - Lead frontend dans N1.RU a introduit Webpack dans plusieurs grands projets qui avaient auparavant leur propre build personnalisé, et y a contribué plusieurs projets. Maxim sait comment créer un bundle de rêve avec Webpack, le faire rapidement et le configurer pour que la configuration reste propre, prise en charge et modulaire.


L'interprétation est différente du rapport - c'est une version grandement améliorée des proflinks. Tout au long de la transcription, les oeufs de Pâques sont éparpillés sur des articles, des plugins, des minificateurs, des options, des transpilers et des preuves des mots du locuteur, des liens vers lesquels il est tout simplement impossible d'insérer un discours. Si vous collectez tout, le niveau bonus dans Webpack s'ouvre :-)

Intégration de Webpack dans un projet typique


Habituellement, la procédure d'implémentation est la suivante: le développeur a lu quelque part un article sur Webpack, décide de le connecter, commence à le construire, d'une manière ou d'une autre, cela commence, tout démarre et pendant un certain temps, webpack-config fonctionne - pendant six mois, un an, deux. Localement, tout va bien - le soleil, l'arc-en-ciel et les papillons. Et puis les vrais utilisateurs viennent:

- À partir d'appareils mobiles, votre site ne se charge pas.
- Tout fonctionne pour nous. Localement, tout va bien!

Au cas où, le développeur va tout profiler et voit que pour les appareils mobiles, le bundle pèse 7 Mo et prend 30 secondes pour se charger . Cela ne convient à personne et le développeur commence à chercher comment résoudre le problème - il peut connecter un chargeur ou trouver un plug-in magique qui résoudra tous les problèmes. Miraculeusement, un tel plugin est localisé. Notre développeur va sur webpack-config, essaie d'installer, mais la ligne de code interfère:

if (process.env.NODE_ENV === 'production') { config.module.rules[7].options.magic = true; } 

La ligne est traduite comme suit: "Si la configuration est en cours d'assemblage pour la production, alors prenez la septième règle et mettez l'option magic = true là-bas." Le développeur ne sait pas quoi faire avec cela et comment le résoudre. C'est une situation où vous avez besoin d'un paquet de rêves.

Comment collecter un paquet de rĂŞves?


Tout d'abord, définissons ce que c'est. Tout d'abord, le bundle de rêve a deux caractéristiques principales:

  • Ça pèse un peu . Le moins de poids - plus rapidement l'utilisateur obtiendra une application qui fonctionne. Vous ne voulez pas que votre site s'ouvre pendant 15 secondes.
  • L'utilisateur tĂ©lĂ©charge uniquement ce qui doit ĂŞtre tĂ©lĂ©chargĂ© pour afficher la page actuelle du site, et pas un octet de plus!

Et pour réduire la taille du bundle, vous devez d'abord évaluer sa taille.

Taux de forfait


La solution la plus populaire est le plugin WebpackBundleAnalyzer . Il recueille des statistiques de construction d'applications et affiche une page interactive oĂą vous pouvez voir l'emplacement et le poids de chaque module.

image

Si cela ne suffit pas, vous pouvez créer un graphe de dépendances à l' aide d' un autre plugin .

image

Ou un graphique Ă  secteurs .

image

Si cela ne suffit pas et que vous souhaitez vendre Webpack à des spécialistes du marketing, vous pouvez créer un univers entier où chaque point est un module, comme une étoile dans l'Univers.

image

Il existe de nombreux outils qui évaluent la taille du bundle et le surveillent. Il y a une option dans la configuration Webpack qui bloque l'assemblage si le paquet pèse trop, par exemple. Il existe un plugin duplicate-package-checker-webpack-plugin qui vous empêchera de créer un bundle si vous avez 2 packages npm de versions différentes, par exemple, Lodash 4.15 et Lodash 4.14.

Comment réduire le forfait


  • Le plus Ă©vident est de brancher UglifyJS pour qu'il minimise JavaScript.
  • Utilisez des chargeurs et des plugins spĂ©ciaux qui compressent et optimisent une ressource spĂ©cifique. Par exemple, css-nano pour css, ou SVGO , qui optimise SVG.
  • Compressez tous les fichiers directement dans Webpack via les plugins gzip / brotli .
  • D'autres outils.

Nous allons maintenant comprendre comment jeter l'excédent du paquet.

Jetez l'excédent


Considérez ceci dans un exemple populaire avec moment.js : import moment from 'moment' . Si vous prenez une application vide, importez moment.js et ReactDOM dedans, puis passez-la via WebpackBundleAnalyzer , vous verrez l'image suivante.

image

Il s'avère que lorsque vous ajoutez un jour, une heure à une date, ou si vous voulez simplement mettre le lien «en 15 minutes» à l'aide de moment.js, vous connectez un total de 230 Ko de code ! Pourquoi cela se produit-il et comment est-il résolu?

Chargement des paramètres régionaux actuellement


Il y a une fonction dans moment.js qui définit les paramètres régionaux:

 function setLocale(locale) { const localePath = 'locale/' + locale + '.js'; this._currentLocale = require(localePath); } 

Le code montre que les paramètres régionaux sont chargés le long du chemin dynamique, c'est-à-dire calculé en runtime. Webpack agit intelligemment et essaie de s'assurer que votre bundle ne plante pas pendant l'exécution du code: il trouve tous les paramètres régionaux possibles dans le projet et les regroupe. Par conséquent, l'application pèse tellement.

image

La solution est très simple - nous prenons un plugin standard de Webpack et lui disons: "Si vous voyez que quelqu'un veut télécharger beaucoup de paramètres régionaux, car ils ne peuvent pas déterminer lequel, il suffit de prendre le russe!"

image

Webpack ne prendra que le russe, et WebpackBundleAnalyzer affichera 54 Ko, ce qui est déjà plus facile de 200 Ko.

Élimination du code mort


La prochaine optimisation qui nous intéresse est l' élimination du code mort . Considérez le code suivant.

 const cond = true; if (!cond) { return false; } return true; someFunction(42); 

La plupart des lignes de ce code ne sont pas nécessaires dans le bundle final - le bloc avec la condition ne sera pas exécuté, la fonction après retour aussi. Tout ce que vous devez laisser, c'est return true . C'est exactement ce qu'est l'élimination du code mort: l'outil de construction détecte le code qui ne peut pas être exécuté et le coupe. Il y a une fonctionnalité intéressante qu'UglifyJS peut faire.

Passons maintenant à l'élimination plus avancée du code mort - méthode d'agitation d'arbre .

Tremblement d'arbre


Disons que nous avons une application qui utilise Lodash . Je doute fortement que quelqu'un utilise tout le Lodash. Très probablement, plusieurs fonctions telles que get , IsEmpty , unionBy ou similaires sont exploitées .

Lorsque nous secouons l'arbre, nous voulons que Webpack «secoue» les modules inutiles et les jette, et nous n'avons que les modules nécessaires. C'est Tree secouant.

Fonctionnement du tremblement d'arbre dans Webpack


Disons que vous avez un code comme celui-ci:

 import { a } from './a.js'; console.log(a); 

Le code est très simple: à partir d'un module, importez la variable a et sortez-la. Mais il y a deux variables dans ce module: a et b . Nous n'avons pas besoin de la variable b et nous voulons la supprimer.

 export const a = 3 export const b = 4 

Lorsque Webpack arrive, il convertit le code d'importation en ceci:

 var d = require(0); console.log(d["a"]); 

Notre import s'est transformée en require , mais console.log pas changé.

La dépendance Webpack est convertie dans le code suivant:

 var a = 3; module.exports["a«] = a; /* unused harmony export b */ var b = 4; 


Webpack a quitté l'exportation de la variable a et a supprimé l'exportation de la variable b , mais a laissé la variable elle-même, en la marquant d'un commentaire spécial. Dans le code converti, la variable b n'est pas utilisée et UglifyJS peut la supprimer.

Le tremblement d'arbre Webpack ne fonctionne que si vous avez une sorte de minifieur de code, comme UglifyJS ou babel-minify .

Prenons des cas plus intéressants - lorsque le tremblement d'arbre ne fonctionne pas.

Quand le tremblement d'arbre ne fonctionne pas


Cas n ° 1. Vous écrivez le code:

 module.exports.a = 3; module.exports.b = 4; 

Exécutez le code via Webpack, et il reste le même. En effet, le bundler organise le tremblement d'arbre uniquement si vous utilisez des modules ES6. Si vous utilisez des modules CommonJS, le tremblement d'arbre ne fonctionnera pas.

Cas n ° 2. Vous écrivez du code avec des modules ES6 et des exportations nommées.

 export const a = 3 export const b = 4 

Si votre code passe par Babel et que vous n'avez pas défini l'option modules sur false , Babel apportera vos modules à CommonJS et Webpack ne pourra à nouveau pas exécuter le tremblement d'arbre, car il ne fonctionne qu'avec les modules ES6.

 module.exports.a = 3; module.exports.b = 4; 

En conséquence, nous devons être sûrs que personne dans notre plan d'assemblage ne transsipera les modules ES6.

Cas n ° 3. Supposons que nous ayons une telle classe inutile qui ne fait rien: export class ShakeMe {} . De plus, nous ne l'utilisons toujours pas. Lorsque Webpack passe par l'importation et l'exportation, Babel transformera la classe en fonction, et le bundler notera que la fonction n'est pas utilisée:

 /* unused harmony e[port b */ var ShakeMe = function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Il semble que tout devrait bien se passer, mais si nous regardons de plus près, nous verrons qu'à l'intérieur de cette fonction il y a une variable globale babelHelpers , à partir de laquelle une fonction est appelée. Ceci est un effet secondaire : UglifyJS voit qu'une fonction globale est appelée et ne coupera pas le code, car il a peur que quelque chose se casse.

Lorsque vous écrivez des cours et que vous les exécutez via Babel, ils ne sont jamais supprimés. Comment est-ce résolu? Il existe un hack standardisé - ajoutez un commentaire /*#__PURE__*/ avant la fonction:

 /* unused harmony export b */ var ShakeMe = /*#__PURE__*/ function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Ensuite, UglifyJS croira au mot que la prochaine fonction est pure. Heureusement, Babel 7 le fait maintenant, et dans Babel 6, rien n'a été supprimé jusqu'à présent.

Règle: si vous avez un effet secondaire quelque part, alors UglifyJS ne fera rien.

Pour résumer:

  • Le tremblement d'arbre ne fonctionne pas pour la plupart des bibliothèques Ă  partir de npm , car elles proviennent toutes de CommonJS et sont construites par l'ancien Babel.
  • Très probablement, le tremblement d'arbre fonctionnera correctement pour les bibliothèques qui sont dĂ©jĂ  prĂ©parĂ©es pour cela , par exemple, Lodash-es, Date-fns et votre code ou vos bibliothèques.
  • UglifyJS est impliquĂ© dans l'assemblage.
  • Modules ES6 d'occasion.
  • Pas d'effets secondaires.

Nous avons compris comment réduire le poids du bundle, et maintenant apprenons-le à ne charger que les fonctionnalités nécessaires.

Nous ne chargeons que les fonctionnalités nécessaires


Nous divisons cette partie en deux. Dans la première partie, seul le code dont l'utilisateur a besoin est chargé : si l'utilisateur visite la page principale de votre site, il ne charge pas les pages du compte personnel. Dans le second, les modifications du code entraînent le rechargement des ressources le plus petit possible .

Nous chargeons uniquement le code nécessaire


Considérez la structure d'une application imaginaire. Il a:

  • Point d'entrĂ©e - APP.
  • Trois pages: accueil, recherche et carte.

image

Le premier problème que nous voulons résoudre est d' émettre un code commun . Notons le code rouge comme code commun à toutes les pages, le cercle vert pour la page principale et la page de recherche. Les chiffres restants ne sont pas particulièrement importants.

image

Lorsque l'utilisateur revient à la recherche à partir de la page principale, il rechargera à la fois la boîte et le cercle une deuxième fois, bien qu'il les ait déjà. Idéalement, nous aimerions voir quelque chose comme ça.

image

C'est bien que Webpack 4 dispose déjà d'un plugin intégré qui le fait pour nous - SplitChunksPlugin . Le plugin supprime le code d'application ou le code des modules de noeud, qui est utilisé par plusieurs morceaux dans un morceau séparé, tout en garantissant que le morceau avec le code commun sera supérieur à 30 Ko, et pour charger la page, vous devez télécharger pas plus de 5 morceaux. La stratégie est optimale: charger trop de petits morceaux n'est pas rentable, et charger trop de morceaux est long et pas aussi efficace que de télécharger moins de morceaux même sur http2. Pour répéter ce comportement sur 2 ou 3 versions de Webpack, j'ai dû écrire 20 à 30 lignes avec des fonctionnalités non documentées. Maintenant, cela est résolu en une seule ligne.

CSS Ă  emporter


Ce serait formidable si nous enlevions toujours le CSS pour chaque morceau dans un fichier séparé. Il existe une solution toute faite pour cela - Mini-Css-Extract-Plugin . Le plugin n'est apparu que dans Webpack 4, et avant cela, il n'y avait pas de solutions adéquates pour une telle tâche - seulement des hacks, des douleurs et des jambes de tir. Le plugin supprime CSS des morceaux asynchrones et a été créé spécifiquement pour cette tâche , qu'il exécute parfaitement.

Recharge minimale possible des ressources


Nous allons voir comment nous assurer que lors de la publication, par exemple, d'un nouveau bloc promotionnel sur la page principale, l'utilisateur rechargera la plus petite partie possible du code .

Si nous avions des versions, tout irait bien. Ici, nous avons la page principale de la version N, et après la sortie du bloc promo - la version N + 1. Webpack fournit un mécanisme similaire dès la sortie de la boîte en utilisant le hachage. Une fois que Webpack a collecté tous les actifs, dans ce cas app.js, il calcule son hachage de contenu et l'ajoute au nom du fichier pour obtenir l'application. [Hash] .js. C'est la version dont nous avons besoin.

image

Vérifions comment cela fonctionne. Activez les hachages, apportez des modifications sur la page principale et voyez si le code de la page principale a vraiment changé. Nous verrons que deux fichiers ont changé: main et app.js.

image

Pourquoi est-ce arrivé, parce que c'est illogique? Pour comprendre pourquoi, jetons un œil à app.js. Il se compose de trois parties:

  • code d'application
  • exĂ©cution du webpack;
  • des liens vers des blocs asynchrones.

Lorsque nous modifions le code en principal, son contenu et son hachage changent, ce qui signifie que le lien vers celui-ci change également dans l'application. L'application elle-même va également changer et doit être redémarrée. La solution à ce problème consiste à diviser app.js en deux blocs: code d'application et runtime webpack et liens vers des blocs asynchrones. Webpack 4 fait tout pour nous avec une option runtimeChunk , qui pèse très peu - moins de 2 Ko en gzip. Le redémarrer pour l'utilisateur est pratiquement sans valeur. RuntimeChunk est activé avec une seule option:

 optimization: { runtimeChunk: true } 

Dans Webpack 3 et 2, nous écrivions 5-6 lignes, au lieu d'une. Ce n'est pas beaucoup plus, mais c'est toujours un inconvénient inutile.

image

Tout est super, nous avons appris à faire des liens et du runtime! Écrivons un nouveau module dans main, libérons-le et - op! - maintenant, en général, tout redémarre.

image

Pourquoi Voyons comment fonctionnent les modules dans webpack.

Modules Webpack


Supposons qu'il existe du code dans lequel vous ajoutez des modules a , b , d et e :

 import a from 'a'; import b from 'b'; import d from 'd'; import e from 'e'; 

Webpack convertit les importations pour exiger: a , b , d et e sont remplacés par require (0), require (1), require (2) et require (3).

 var a = require(0); var b = require(1); var d = require(2); var e = require(3); 

Imaginez une image qui se produit très souvent: vous écrivez un nouveau module c import c from 'c'; et collez-le quelque part au milieu:

 import a from 'a'; import b from 'b'; import c from 'c'; import d from 'd'; import e from 'e'; 

Lorsque Webpack traite tout, il convertit l'importation du nouveau module en require (2):

 var a = require(0); var b = require(1); var c = require(2); var d = require(3); var e = require(4); 

Les modules d et e , qui étaient 2 et 3, recevront les numéros 3 et 4 - le nouvel identifiant. Une conclusion simple en découle: utiliser des numéros de série comme id est un peu idiot, mais Webpack le fait.

N'utilisez pas le numéro de série comme identifiant unique

Pour résoudre le problème, il existe une solution Webpack intégrée - HashedModuleIdsPlugin :

 new webpack.HashedModuleIdsPlugin({ hashFunction: 'md4′, hashDigest:'base64′, hashDigestLength: 4, }), 

Ce plugin utilise 4 caractères de hachage md4 au lieu de l'identifiant numérique du chemin absolu vers le fichier. Avec lui, notre besoin se transformera en ceux-ci:

 var a = require('YmRl'); var b = require('N2Fl'); var c = require('OWE4′); var d = require('NWQz'); var e = require('YWVj'); 

Au lieu de chiffres, des lettres sont apparues. Bien sûr, il y a un problème caché - c'est une collision de hachages . Nous sommes tombés dessus une fois et pouvons vous conseiller d'utiliser 8 caractères au lieu de 4. Après avoir configuré correctement les hachages, tout fonctionnera comme nous le voulions à l'origine.

Nous savons maintenant comment collecter des bundles de rĂŞve.

  • RĂ©duisez .
  • Utilisez le fractionnement de code .
  • Configurez des hachages .

Nous avons appris Ă  collectionner, et maintenant nous allons travailler sur la vitesse.

Comment assembler rapidement un bundle de rĂŞve?


Dans notre N1.RU, la plus grande application se compose de 10 000 modules, et sans optimisation, cela prend 28 minutes. Nous avons pu accélérer le montage à deux minutes! Comment avons-nous fait ça? Il existe 3 façons d'accélérer les calculs, et les trois sont applicables à Webpack.

Parallélisation d'assemblage


La première chose que nous avons faite a été de paralléliser l'assemblage . Pour cela nous avons:

  • HappyPackPlugin , qui encapsule vos chargeurs dans d'autres chargeurs, et prend tous les calculs qui sont encapsulĂ©s dans des processus sĂ©parĂ©s. Cela permet, par exemple, de parallĂ©liser Babel et node-sass.
  • chargeur de fil . Fonctionne Ă  peu près de la mĂŞme manière que HappyPackPlugin, n'utilise pas non plus des processus, mais un pool de threads. Passer Ă  un thread sĂ©parĂ© est une opĂ©ration coĂ»teuse, utilisez-la avec prĂ©caution et uniquement si vous souhaitez encapsuler des opĂ©rations gourmandes en ressources et lourdes, telles que babel ou node-sass. Pour charger json, par exemple, la parallĂ©lisation n'est pas nĂ©cessaire, car elle se charge rapidement.
  • Les plugins et chargeurs que vous utilisez sont probablement dĂ©jĂ  dotĂ©s d' outils de parallĂ©lisation intĂ©grĂ©s - il suffit de regarder. Par exemple, cette option se trouve dans UglifyJS .

Mise en cache des résultats de génération


La mise en cache des résultats d'assemblage est le moyen le plus efficace d'accélérer l'assemblage de Webpack.

La première solution que nous avons est le cache-loader . Il s'agit d'un chargeur qui entre dans une chaîne de chargeurs et enregistre le résultat de la création d'un fichier spécifique pour une chaîne de chargeurs spécifique dans le système de fichiers. Lors du prochain assemblage du bundle, si ce fichier est sur le système de fichiers et a déjà été traité avec cette chaîne, cache-loader prendra les résultats et n'appellera pas les chargeurs qui sont derrière eux, par exemple, Babel-loader ou node-sass.

Le graphique montre le temps d'assemblage. Barre bleue - 100% de temps de construction, sans chargeur de cache, et avec elle - 7% plus lent. En effet, le chargeur de cache passe plus de temps à économiser les caches sur le système de fichiers. Déjà lors du deuxième montage, nous avons réalisé un bénéfice tangible - le montage était 2 fois plus rapide.

image

La deuxième solution est plus sophistiquée - HardSourcePlugin . La principale différence: le cache-chargeur n'est qu'un chargeur qui ne peut fonctionner que dans une chaîne de chargeurs avec du code ou des fichiers, et HardSourcePlugin a un accès presque complet à l'écosystème Webpack, peut fonctionner avec d'autres plugins et chargeurs, et il étend l'écosystème pour la mise en cache un peu. Le graphique ci-dessus montre qu'au premier lancement, le temps de build a augmenté de 37%, mais au deuxième lancement avec tous les caches, nous avons accéléré 5 fois.

image

La meilleure partie est que vous pouvez utiliser les deux solutions ensemble, ce que nous faisons chez N1.RU. Soyez prudent, car il y a des problèmes avec les caches, dont je parlerai un peu plus tard.

Les plugins / chargeurs que vous utilisez déjà peuvent avoir des mécanismes de mise en cache intégrés . Par exemple, babel-loader a un système de mise en cache très efficace, mais pour une raison quelconque, il est désactivé par défaut. La même fonctionnalité se trouve dans awesome-typeScript-loader . Le plugin UglifyJS a également une mise en cache, ce qui fonctionne très bien. Il nous a accélérés de plusieurs minutes.

Et maintenant les problèmes.

Problèmes de mise en cache


  • Le cache peut ne pas valider correctement .
  • Les solutions appliquĂ©es peuvent ne pas fonctionner avec les plugins connectĂ©s, les chargeurs, votre code ou les uns avec les autres . Ă€ cet Ă©gard, le cache-chargeur est une solution simple et sans tracas. Mais avec HardSourcePlugin, vous devez ĂŞtre plus prudent.
  • Il est difficile de faire ses dĂ©buts si tout est cassĂ© . Lorsque la mise en cache ne fonctionne pas correctement et qu'une erreur incomprĂ©hensible se produit, il sera très difficile de dĂ©terminer le problème.

Comment Ă©conomiser sur la production?


La dernière façon d'accélérer un processus est de ne faire aucune partie du processus. Réfléchissons à la façon dont vous pouvez économiser sur la production? Que pouvons-nous ne pas faire? La réponse est courte - nous ne pouvons rien faire ! Nous n'avons pas le droit de refuser quelque chose en production, mais nous pouvons économiser beaucoup en développement.

Sur quoi Ă©conomiser:

  • Ne rĂ©cupĂ©rez pas la carte source avant d'en avoir besoin.
  • Utilisez style-loader au lieu d'un schĂ©ma sympa avec suppression et traitement css via des chargeurs css. Le chargeur de style lui-mĂŞme est très rapide, car il prend la ligne css et la pousse dans une fonction qui insère cette ligne dans la balise de style.
  • Vous ne pouvez laisser dans la liste des navigateurs que le navigateur que vous utilisez spĂ©cifiquement - il s'agit très probablement du dernier chrome . Cela va considĂ©rablement s'accĂ©lĂ©rer .
  • Abandonner complètement toute optimisation des ressources : depuis UglifyJS, css-nano, gzip / brotli.

L'accélération de la construction est la parallélisation, la mise en cache et le refus des calculs. En suivant ces trois étapes simples, vous pouvez accélérer beaucoup.

Comment configurer le webpack?


Nous avons compris comment assembler un bundle de rĂŞve et comment l'assembler rapidement, et maintenant nous allons voir comment configurer Webpack pour ne pas nous tirer une balle dans la jambe Ă  chaque fois que vous changez la configuration.

Evolution de la configuration dans le projet


Un chemin de configuration Webpack typique dans un projet commence par une configuration simple . Au début, vous insérez simplement Webpack, Babel-Loader, Sass-Loader et tout va bien. Puis, de manière inattendue, certaines conditions apparaissent sur process.env et vous insérez les conditions. Un, deuxième, troisième, de plus en plus, jusqu'à ce qu'une condition avec une option «magique» soit ajoutée. Vous comprenez que tout est déjà assez mauvais, et il vaut mieux simplement dupliquer les configurations pour le développement et la production, et faire des corrections deux fois. Tout sera plus clair. Si vous aviez une pensée: "Quelque chose ne va pas ici?", Alors le seul conseil de travail est de garder la configuration en ordre . Je vais vous dire comment nous procédons.

Gardez la configuration en ordre


Nous utilisons le package webpack-merge . Il s'agit d'un package npm créé pour combiner plusieurs configurations en une seule. Si vous n'êtes pas à l'aise avec la stratégie de fusion par défaut, vous pouvez la personnaliser.


4 :

  • Loaders.
  • Plugins.
  • Presets.
  • Parts.

.

Plugin/Loader


, , API, , .

Cela ressemble Ă  ceci:

 /** *  JSdoc * @param {Object} options * @see    */ module.exports = function createPlugin(options) { return new Plugin(options); }; 

, , , . , url-loader :

 /** * url-loader    file-loader.        * * @example * -   some-image.png.     url-loader,  url-loader    * 1.    ,  url-loader    base64  * 2. , url-loader    outputPath + name     ,     . *    some-image.png,     outputPath/images/some-image.12345678hash.png,  url-loader  * publicPath/images/some-image.12345678hash.png * * @param {string} prefix    * @param {number} limit    ,    * @return {Object} loader   * @see https://www.npmjs.com/package/url-loader */ 

, , , , , , . , , , , url-loader. :

 function urlLoader(prefix = 'assets', limit = 100) { return { loader: 'url-loader', options: { limit, name: `${prefix}/[name].[hash].[ext]` } }; }; 

. , Loader .

Preset


webpack. , , , webpack, . — , , scss-:

 { test: /\.scss$/, use: [cssLoader, postCssLoader, scssLoader] } 

.

Part


— , . , , . , :

 entry: { app: './src/Frontend/app.js' }, output: { publicPath: '/static/cabinet/app/', path: path.resolve('www/static/app') }, 

:

  • , , , json, , , splitChunks.
  • dev , , js/css
  • Part , output, publicPath, entry-point , , source map.

image

Webpack-merge . , . webpack-merge 3-7 , Babel-loader, . , .


Pour résumer. , . , webpack — . , .

, !

— Frontend Conf . , — , , Frontend Conf ++ .

- ? FrontenConf ++ , 27 28 . 27 , 15 . — !

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


All Articles