4 tips untuk mengoptimalkan aplikasi webpack Anda

Halo semuanya!

Selama bekerja dengan webpack, saya telah mengumpulkan beberapa tips menarik untuk membantu Anda mempersiapkan aplikasi yang dioptimalkan dengan sempurna. Ayo mulai!

Kucing front-end menatap webpack dan mengatakan 'Belissimo'



1. Gunakan async cepat alih-alih regenerator-runtime


Biasanya, pengembang menggunakan @ babel / preset-env untuk mengonversi semua sintaks modern ke ES5.

Dengan preset ini, pipa transformasi fungsi asinkron terlihat seperti ini:
Source asynchronous function -> Generator -> Function menggunakan regenerator-runtime

Contoh
1. Fungsi asinkron asli

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

2. Generator

 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. Berfungsi menggunakan regenerator-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); }; }(); 


Dengan fast-async, pipa disederhanakan untuk:
Sumber Fungsi Asinkron -> Fungsi Menggunakan Janji

Contoh
1. Fungsi asinkron asli

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

2. Fungsi menggunakan janji

 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); }); }; 


Karena ini, sekarang kami tidak memiliki regenerator-runtime pada klien dan pembungkus tambahan dari transformasi.

Untuk membawa async cepat ke proyek Anda, Anda harus:

1. Pasang

 npm i fast-async 

2. Perbarui konfigurasi babel

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

Bagi saya, optimasi ini mengurangi ukuran file js sebesar 3,2%. Agak, tapi bagus :)

2. Gunakan transformasi longgar


Tanpa konfigurasi khusus, @ babel / preset-env mencoba membuat kode sedekat mungkin dengan spesifikasi.

Tetapi, kemungkinan besar, kode Anda tidak terlalu buruk dan tidak menggunakan semua kasus ekstrem yang mungkin dari spesifikasi ES6 +. Kemudian semua overhead tambahan dapat dihilangkan dengan mengaktifkan transformasi longgar untuk preset-env:

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

Contoh cara kerjanya dapat ditemukan di sini .

Dalam proyek saya, ini mengurangi ukuran bundel sebesar 3,8%.

3. Konfigurasikan minifikasi js dan css dengan tangan Anda


Pengaturan default untuk minificator hanya berisi transformasi yang tidak dapat dipecah oleh programmer. Tapi kami suka menimbulkan masalah?
Coba baca pengaturan untuk js minifier dan css minifier Anda (saya menggunakan cssnano ).

Setelah mempelajari dok, saya membuat konfigurasi ini:

 // 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 }, }, }), ], }, }; /* ... */ 

Akibatnya, ukuran file js menurun 1,5%, dan css - sebesar 2%.

Mungkin Anda bisa melakukan yang lebih baik?

UPD 01/11/2019: UglifyJsPlugin sudah tidak digunakan lagi, webpack sekarang menggunakan TerserWebpackPlugin . Gunakan itu.

4. Gunakan null-loader untuk menghapus dependensi yang tidak perlu


Pengembang gsap memiliki perpustakaan yang bagus untuk membuat animasi. Tetapi karena fakta bahwa itu berasal dari 2008, beberapa fitur tetap di dalamnya.

Yakni yang ini . Berkat itu, TweenMax menarik 5 plugin dan easyPack, yang sepenuhnya opsional.

Saya perhatikan tiga plugin yang berlebihan di dalam saya dan hentikan menggunakan 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', }, ] }, }; /* ... */ 

Dan 106 kb berubah menjadi 86. Ya!

Null-loader masih dapat digunakan untuk menghapus polyfill yang tidak perlu yang ditanam oleh penulis perpustakaan untuk kami.

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


All Articles