4 conseils pour optimiser votre application webpack

Bonjour à tous!

Au cours de mon travail avec le webpack, j'ai accumulé quelques astuces intéressantes qui vous aideront à préparer une application parfaitement optimisée. Commençons!

Un chat frontal regarde le webpack et dit 'Belissimo'



1. Utilisez fast-async au lieu de régénérateur-runtime


En règle générale, les développeurs utilisent @ babel / preset-env pour convertir toute la syntaxe moderne en ES5.

Avec ce préréglage, le pipeline de transformations des fonctions asynchrones ressemble à ceci:
Fonction asynchrone source -> Générateur -> Fonction utilisant le régénérateur-runtime

Exemple
1. La fonction asynchrone d'origine

const test = async () => { await fetch('/test-api/', { method: 'GET' }); } 

2. Générateur

 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const test = (() => { var _ref = _asyncToGenerator(function* () { yield fetch('/test-api/', { method: 'GET' }); }); return function test() { return _ref.apply(this, arguments); }; })(); 

3. Fonction utilisant le régénérateur-runtime

 'use strict'; function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } var test = function () { var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return fetch('/test-api/', { method: 'GET' }); case 2: case 'end': return _context.stop(); } } }, _callee, undefined); })); return function test() { return _ref.apply(this, arguments); }; }(); 


Avec fast-async, le pipeline est simplifié pour:
Fonction asynchrone source -> Fonction utilisant des promesses

Exemple
1. La fonction asynchrone d'origine

 const test = async () => { await fetch('/test-api/', { method: 'GET' }); } 

2. Fonction à l'aide de promesses

 var test = function test() { return new Promise(function ($return, $error) { return Promise.resolve(fetch('/test-api/', { method: 'GET' })).then(function ($await_1) { try { return $return(); } catch ($boundEx) { return $error($boundEx); } }, $error); }); }; 


Pour cette raison, nous n'avons plus de régénérateur-runtime sur le client et de wrappers supplémentaires provenant des transformations.

Pour intégrer une asynchronisation rapide dans votre projet, vous devez:

1. Installez-le

 npm i fast-async 

2. Mettre à jour la config du babel

 // .babelrc.js module.exports = { "presets": [ ["@babel/preset-env", { /* ... */ "exclude": ["transform-async-to-generator", "transform-regenerator"] }] ], /* ... */ "plugins": [ ["module:fast-async", { "spec": true }], /* ... */ ] } 

Pour moi, cette optimisation a réduit la taille des fichiers js de 3,2%. Un peu, mais sympa :)

2. Utilisez des transformations lâches


Sans configuration spéciale, @ babel / preset-env essaie de générer du code aussi proche que possible de la spécification.

Mais, très probablement, votre code n'est pas si mauvais et n'utilise pas tous les cas extrêmes possibles de la spécification ES6 +. Ensuite, tous les frais généraux supplémentaires peuvent être supprimés en activant des transformations lâches pour preset-env:

 // .babelrc.js module.exports = { "presets": [ ["@babel/preset-env", { /* ... */ "loose": true, }] ], /* ... */ } 

Un exemple de la façon dont cela fonctionne peut être trouvé ici .

Dans mon projet, cela a réduit la taille du bundle de 3,8%.

3. Configurez la minification js et css avec vos mains


Les paramètres par défaut des minificateurs ne contiennent que les transformations qui ne peuvent pas être interrompues par le programmeur. Mais nous aimons causer des problèmes?
Essayez de lire les paramètres du minifier js et de votre minifier css (j'utilise cssnano ).

Après avoir étudié les quais, j'ai fait cette config:

 // webpack.config.js const webpackConfig = { /* ... */ optimization: { minimizer: [ new UglifyJsPlugin({ uglifyOptions: { compress: { unsafe: true, inline: true, passes: 2, keep_fargs: false, }, output: { beautify: false, }, mangle: true, }, }), new OptimizeCSSPlugin({ cssProcessorOptions: { "preset": "advanced", "safe": true, "map": { "inline": false }, }, }), ], }, }; /* ... */ 

En conséquence, la taille des fichiers js a diminué de 1,5% et css - de 2%.

Peut-être pouvez-vous faire mieux?

UPD 01/11/2019: UglifyJsPlugin est obsolète, webpack utilise maintenant TerserWebpackPlugin . Utilisez-le.

4. Utilisez null-loader pour supprimer les dépendances inutiles


Les développeurs de gsap ont une excellente bibliothèque pour créer des animations. Mais en raison du fait qu'il date de 2008, certaines fonctionnalités y sont restées.

À savoir , celui-ci . Grâce à lui, TweenMax tire 5 plugins et l'EasyPack, qui sont complètement optionnels.

J'ai remarqué trois plugins redondants en moi et les ai coupés en utilisant null-loader :

 // webpack.config.js const ignoredGSAPFiles = ['BezierPlugin', 'DirectionalRotationPlugin', 'RoundPropsPlugin']; const webpackConfig = { /* ... */ module: { rules: [ /* ... */ { test: /\.js$/, include: ignoredGSAPFiles.map(fileName => resolve('node_modules/gsap/' + fileName)), loader: 'null-loader', }, ] }, }; /* ... */ 

Et 106 kb se transforment en 86. Oui!

Null-loader peut toujours être utilisé pour supprimer les polyfills inutiles que les auteurs de la bibliothèque ont soigneusement plantés pour nous.

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


All Articles