Мы относимся к технологиям, которые используем как делать покупки на яндекс маркете.
Смотрим спецификацию, читаем обзоры и, если проект получил много звезд на Github, он проходит спецификацию, к тому же выполнение это недорого, мы Мы покупаем установить.
Такой подход порой очень сильно бьет граблями по голове, и тогда еще приходится разбираться, что происходит.
Фон
В статья один из авторов свернуть рассматриваются две оптимизации, одна называется устранение мертвого кода , и второй тряска дерева .Автор показывает, что Tree Shaking имеет гораздо больше возможностей для сжатия кода.
И в доказательство он высказывает несколько мыслей о рецептах пирогов и разбитых яйцах.
Ох уж эти метафоры! Эта идея (о тряске деревьев, а не о пироге и яйцах) была подхвачена командой разработчиков вебпака и стала официально поддерживаться с версии 2.0.
Проблема
Я бы не писал, если бы технология приносила хоть какой-то результат на реальных проектах.На практике размер конечной сборки либо не уменьшается вообще, либо уменьшается на величину статистической погрешности.
Некоторые, конечно, догадываются и даже пишут статьи на Хабре .
Но людей, рассуждающих о преимуществах Tree-Shaking перед подсветкой мертвого кода в вебпаке, не меньше, по крайней мере, среди посетителей конференции и среди моих коллег.
Как это должно было работать?
Идея так же проста, как бак .
- Конструктор просматривает дерево модулей и помечает неиспользуемые импорты специальными комментариями.
Так:
.
/* unused harmony export square */ function square(x) { return x * x;} .
- Следующий этап UglifyJS, который по умолчанию приклеен к вебпаку, помимо всего, что мы от него ожидаем, безжалостно вырезает код, отмеченный этими самыми комментариями.
- ВЫГОДА!
Когда это не работает?
Допустим, все как в документации.
Два файла index.js и Module.js // index.js
import {cube} from '.
/module'
console.log(cube(x))
// module.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
Если теперь запустить вебпак в режиме оптимизации и минификации, то все будет работать как положено.
( код ) webpack --optimize-minimize index.js out.js
А вот если в файл с модулями при наличии бабель-загрузчика добавить какой-нибудь, даже самый маленький класс с экспортом, то начинается ад. Класс попадет в окончательную сборку как функция, созданная Babel. ( код ) //module.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
export class MyClass {
print(){
console.log('find me');
}
}
Как это произошло?
Все дело в том, что UglifyJS боится выкинуть что-то ненужное.Оно и понятно: лучше на пару сотен байт больше, просто чтобы не сломалось.
Итак, представьте, что UglifyJS получает на вход следующий код: /* unused harmony export MyClass */
var MyClass = function () {
function MyClass() {
babelHelpers.classCallCheck(this, MyClass);
}
MyClass.prototype.turn = function print() {
console.log('find me');
};
return MyClass;
}();
MyClass после компиляции Babel каким-то образом сумел распознать себя как класс.
В целом, UglifyJS мало что знает о том, как команда Babel видит реализацию классов в ES5. Поэтому он сдается, оставляя этот неизвестный, неиспользованный позор в вашей финальной сборке.
В репозитории даже есть ошибка по этому поводу.
веб-пакет , и ребята обещают всё исправить в 4-я версия .
Rollup, кстати, еще не так давно тоже работал только на примерах с математикой, но в последних версиях ребята исправили ошибку.
( сломанный пример , рабочий пример ).
Мораль
Так вот, купив вебпак, в том числе и для трэкшейка, я получил околонулевую выгоду в этом направлении.А слово «тряска дерева» теперь вызывает у меня нервный смех, икоту и неудержимый сарказм.
Так что же нам теперь делать?
Во-первых, откажитесь от веб-пакета и используйте мой.принципиально новый коллекционер , который лишен как этих недостатков, так и многих других.
Помимо классических сборок, он варит крафтовое пиво и готовит чиабатта-бургеры.
Извините, я не удержался.
А если серьезно, то есть очень простой способ исправить ситуацию: веб-пакету необходимо добавить специальную директиву /*#__PURE__*/
, который бы сказал UglifyJS, что этого неизвестного монстра можно вырезать в виде функции.
Ох уж эти костыли.
И выглядит это примерно так: /* unused harmony export MyClass */
var MyClass = /*#__PURE__*/ function () {
function MyClass() {
babelHelpers.classCallCheck(this, MyClass);
}
MyClass.prototype.turn = function print() {
console.log('find me');
};
return MyClass;
}();
Еще пара итераций и мы изобретем статическую типизацию ;) Рабочий пример Кстати, новая версия Babel 7 уже это делает. К сожалению, он все еще находится в стадии бета-тестирования, что, похоже, намекает на невозможность его использования прямо сейчас.
Но если вы смелы и решительны, вы можете попробовать обновиться.
Забегая вперед, скажу, что есть несколько решений, которые работают прямо сейчас.
О них я расскажу в следующей статье.
Возможно, они сэкономят чьи-то нервы и время.
И нам пора переходить к выводам.
выводы
- Сомневайтесь во всем.
Проверьте информацию.
Даже эта статья.
Эта практика сэкономит вам много нервов и времени.
- Экосистема JavaScript иногда страдает от сбоев на стыке технологий.
Здесь тоже из-за того, что Babel ничего не сообщил UglifyJS через вебпак о своем формате классов для ES5, произошло недоразумение.
При этом в Babel это уже почти исправлено, о чем, конечно же, ребята из webpack не знают и хотят исправить в следующем релизе.
Часть 2 Теги: #webpack #JavaScript #treeshaking #Разработка сайтов #JavaScript #Оптимизация клиента
-
Ноутбук – Детка, Ты Прошел Долгий Путь.
19 Oct, 24 -
Такс Дроид
19 Oct, 24 -
Слухи С Картинками: Wacom Intuos 4
19 Oct, 24