- PVSM.RU - https://www.pvsm.ru -
Всем привет!
За время моей работы с вебпаком у меня накопилась пара интересных советов, которые помогут вам приготовить отлично оптимизированное приложение. Приступим!
Обычно, разработчики используют @babel/preset-env [1], чтобы преобразовывать весь современный синтаксис в ES5.
С этим пресетом пайплайн преобразований асинхронных функций выглядит так:
Исходная асинхронная функция -> Генератор [2] -> Функция [3], использующая regenerator-runtime [4]
const test = async () => {
await fetch('/test-api/', { method: 'GET' });
}
2. Генератор
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. Функция, использующая 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);
};
}();
С fast-async [5] пайплайн упрощается до:
Исходная асинхронная функция -> Функция, использующая промисы
const test = async () => {
await fetch('/test-api/', { method: 'GET' });
}
2. Функция, использующая промисы
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);
});
};
Благодаря этому, теперь у нас нет regenerator-runtime на клиенте и лишних оберток от трансформаций.
Чтобы подвести fast-async в свой проект, надо:
1. Установить его
npm i fast-async
2. Обновить конфиг бабеля
// .babelrc.js
module.exports = {
"presets": [
["@babel/preset-env", {
/* ... */
"exclude": ["transform-async-to-generator", "transform-regenerator"]
}]
],
/* ... */
"plugins": [
["module:fast-async", { "spec": true }],
/* ... */
]
}
У меня эта оптимизация уменьшила размер js файлов на 3.2%. Мелочь, а приятно :)
Без специальной настройки @babel/preset-env [1] пытается сгенерировать как можно более близкий к спецификации код.
Но, скорее всего, ваш код не настолько плох и не использует все возможные крайние случаи ES6+ спецификации. Тогда весь лишний оверхед можно убрать, включив loose трансформации для preset-env:
// .babelrc.js
module.exports = {
"presets": [
["@babel/preset-env", {
/* ... */
"loose": true,
}]
],
/* ... */
}
Пример того, как это работает, можно найти тут [6].
В моем проекте это уменьшило размер бандла на 3.8%.
Дефолтные настройки для минификаторов содержат только те трансформации, которые не смогут ничего сломать у программиста. Но мы ведь любим доставлять себе проблемы?
Попробуйте почитать настройки минификатора js [7] и своего минификатора css (я использую cssnano [8]).
Изучив доки, я сделал такой конфиг:
// 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 },
},
}),
],
},
};
/* ... */
В результате размер js файлов уменьшился на 1.5%, а css — на 2%.
Может, у вас получится лучше?
У разработчиков gsap [9] получилась отличная библиотека для создания анимаций. Но из-за того, что она берет свое начало еще из 2008 года, в ней остались некоторые особенности.
А именно вот эта [10]. Благодаря ней TweenMax тянет за собой 5 плагинов и easePack, которые юзать совершенно необязательно.
У себя я заметил три лишних плагина и выпилил их с помощью null-loader [11]:
// 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',
},
]
},
};
/* ... */
И 106 кб превращаются в 86. Та-да!
Null-loader еще можно использовать для удаления ненужных полифиллов, которые авторы библиотек заботливо нам подложили.
Автор: AndreasCag
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/294681
Ссылки в тексте:
[1] @babel/preset-env: https://github.com/babel/babel/tree/master/packages/babel-preset-env
[2] Генератор: https://babeljs.io/docs/en/babel-plugin-transform-async-to-generator
[3] Функция: https://babeljs.io/docs/en/babel-plugin-transform-regenerator
[4] regenerator-runtime: https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime
[5] fast-async: https://github.com/MatAtBread/fast-async
[6] тут: http://2ality.com/2015/12/babel6-loose-mode.html
[7] минификатора js : https://github.com/mishoo/UglifyJS2
[8] cssnano: https://github.com/cssnano/cssnano
[9] gsap: https://github.com/greensock/GreenSock-JS
[10] вот эта: https://github.com/greensock/GreenSock-JS/blob/master/src/esm/TweenMax.js#L24
[11] null-loader: https://github.com/webpack-contrib/null-loader
[12] Источник: https://habr.com/post/425215/?utm_campaign=425215
Нажмите здесь для печати.