Меня зовут Илья Гольдфарб, я разработчик интерфейса Яндекса.
Мне интересно наблюдать за тем, как развиваются инструменты для построения фронтендов, поэтому я стараюсь изучать изменения в каждом выпуске популярных решений.
В преддверии выхода пятой версии вебпака хочу рассказать о его, казалось бы, минорном релизе 4.26.0 от 19 ноября 2018 года, где неожиданно и без объявления войны изменилась дефолтная версия минификатора.
Раньше это был пакет UglifyJS, но теперь он использует Terser, ответвление UglifyES — ветки UglifyJS, которая может сжимать код как ES5, так и ES6. Терсер появился, когда главный сопровождающий отказался поддерживать и развивать UglifyES. Однако разработка UglifyJS также прекратилась с августа 2018 года, когда был выпущен последний выпуск.
В новом форке исправлены некоторые ошибки и немного переработан код. API этих минификаторов совместим, но они дают разные результаты сжатия.
Обычно изменения такого уровня происходят только в крупных, а не второстепенных обновлениях.
Из-за этого многие разработчики могут не обратить внимания на нововведение.
Конечно, в большинстве случаев все будет работать, но никто не хочет оказаться тем, у кого во время производства своего проекта возникают ошибки из-за системы сборки и минификации.
Вся эта история вдохновила меня на небольшое личное исследование сжатия.
Вот вопросы, которые я задал:
- Что лучше сжимает ES5, Terser или UglifyJS?
- Что загружается быстрее: сжатая версия ES5 от Terser или версия UglifyJS?
- Какая версия весит больше: ES5 или ES6? И как TypeScript на это влияет?
- Есть ли большая разница между настройками по умолчанию и настройками вручную?
- А что, если это не вебпак? Кто производит меньшую сборку: Rollup или веб-пакет?
Всего было 3 529 695 байт неминифицированного кода (720 393 байта gzip).
Что лучше сжимает ES5, Terser или UglifyJS?
Я взял последнюю доступную версию UglifyJS, которая поставляется с веб-пакетом Terser с опцией ES5 и использовал те же настройки сжатия.
Размер в байтах | Размер в байтах (gzip) | |
UglifyJS | 1 050 376 | 285 290 |
Терсер | 1 089 282 | 292 678 |
Что загружается быстрее: сжатая версия ES5 от Terser или версия UglifyJS?
Производительность я измерял с помощью стандартных DevTools Яндекс Браузера.Я загрузил страницу 12 раз и взял значение Scripting (время выполнения скрипта), отбросив первые три измерения.
UglifyJS — 221 мс (ошибка 2,8%).
Терсер - 226 мс (погрешность 2,7%).
Итог: значения слишком малы для такой ошибки; их можно считать одинаковыми.
Мы также пришли к выводу, что этот метод не подходит для измерения времени загрузки.
Скорость кода я не измерял и не сравнивал, так как разные коды работают по-разному.
Разработчики каждого проекта должны самостоятельно разобраться в этом вопросе.
Какая версия весит больше: ES6 или ES5? И как TypeScript на это влияет?
Чтобы сравнить две версии и сосредоточиться исключительно на технологии, я взял Плагины Babel и сделал четыре сборки:- ES5: все плагины с пометкой es2016 + плагин для Object.assign + более поздние плагины + экспериментальные плагины, в качестве цели в tsconfig установлено значение ES5;
- ES5 (ts esnext): все плагины с пометкой es2016 + плагин для Object.assign + все более поздние плагины + экспериментальные плагины, в качестве цели в tsconfig установлено значение esnext;
- ES6: только плагины для es2017 и более поздних версий + экспериментальные плагины, в tsconfig для цели установлено значение ES6;
- ES6 (ts esnext): только плагины для es2017 и более поздних версий + экспериментальные плагины, в tsconfig для цели установлено значение esnext.
Размер в байтах | Размер в байтах (gzip) | |
ES5 | 1 186 520 | 322 071 |
ES5 (тс эснекст) | 1 089 282 | 292 678 |
ES6 | 1 087 220 | 292 232 |
ES6 (тс эснекст) | 1 087 220 | 292 232 |
Так неожиданно получилось, потому что Angular написан на TypeScript, а Vue и React на JavaScript. Terser, как и Uglify, при сборке с вебпаком не может вырезать неиспользуемый кусок кода, поставляемый Typescript из Angular. Это ошибка компиляции для этого примера.
В сборке на другом проекте его может не быть и разница будет гораздо меньше.
Вы также можете видеть, что объем кода ES6 всего на 2062 байта меньше, чем у ES5. На любимом проекте я получил совсем другой результат: кода ES6 на 3-6% больше, чем ES5. Это объясняется несколькими факторами, двумя основными из которых являются: 1. Помощник Babel для наследования классов вставляется один раз и далее стоит четыре байта (e(a,b)), а в ES6 используется нативное наследование стоимостью 15 байт (класс a расширяет b).
2. Метод объявления переменных.
В ES5 это переменные, и они отлично сжимаются.
Но в ES6 это let и const, которые сохраняют порядок инициализации и не объединяются друг с другом.
Небезопасная агрессивная минификация, такая как принудительное использование стрелочных функций или использование свободной настройки, поможет уменьшить размер кода ES6. Будьте внимательны и учитывайте тонкости.
Например, в Firefox стрелка функционирует в в четыре раза медленнее , чем обычно, но в Хроме разницы нет. Поэтому однозначно ответить на вопрос невозможно: результат сильно зависит от кода и целевой среды выполнения.
Есть ли большая разница между настройками по умолчанию и настройками вручную?
Давайте сравним, можно ли получить меньший размер файла, если немного подправить настройки.Например, укажем, что минификацию необходимо повторить пять раз.
По умолчанию он запускается только один раз.
Размер в байтах | Размер в байтах (gzip) | |
Терсер (по умолчанию) ES5 | 1 097 141 | 294 306 |
Терсер (проходит 5) ES5 | 1 089 312 | 292 408 |
Уродовать (по умолчанию) ES5 | 1 091 350 | 294 845 |
Уродство (проходит 5) ES5 | 1 050 363 | 284 618 |
Поэтому всегда необходимо корректировать настройки сжатия.
Кстати, пятикратная минификация не означает, что сборка займет в пять раз больше времени.
Например, в этом тестовом проекте однократная минификация занимает 18 секунд, пятикратная минификация — 38, а десятикратная — 49. Рекомендую экспериментальным путем найти идеальное значение для вашего проекта, после чего минификация завершится.
остановитесь, и код не изменится.
Обычно это от 5 до 10. Есть еще куча других вариантов: comment:false вырезает все комментарии о лицензиях (хотя это юридический вопрос), а hoist_funs:true группирует функции в одном месте, что позволяет лучше оптимизировать переменные.
В идеале нужно пройти все настройки .
Кто производит меньшую сборку: Rollup или веб-пакет?
Свернуть — альтернативный коллектор со встроенным механизмом встряхивания дерева.Для теста я сделал сборку на Rollup 0.67.4 с теми же настройками, что и у webpack.
Размер в байтах | Размер в байтах (gzip) | |
Накопительный пакет ES5 (Uglify) | 990 497 | 274 105 |
Накопительный пакет ES5 (Терсер) | 995 318 | 272 532 |
веб-пакет ES5 (Uglify) | 1 050 363 | 284 618 |
веб-пакет ES5 (Терсер) | 1 089 312 | 292 408 |
Это произошло по нескольким причинам: 1. Webpack содержит костыли для крайних случаев.
Например, этот код оборачивает каждый вызов функции из другого модуля в Object().
Это сделано для того, чтобы контекст модулей без использования strict не передавался в модули с use strict. Хорошо написанные проекты без сторонних зависимостей не нуждаются в обертке, но иногда в сборке задействовано нечто большее, чем просто хорошо написанный код. И в этом плане вебпак выглядит надежнее.
Rollup, в свою очередь, считает, что все модули — это ES6-модули, и они всегда исполняются в use strict, поэтому для него этой проблемы просто не существует. Важный вопрос — как такие костыли вебпаков влияют на производительность.
Давайте представим, что мы написали идеальный код, который не нуждается в дополнительных обертках, но все равно каждый вызов функции будет проходить через них.
Это добавляет небольшие накладные расходы на выполнение: примерно одну сотую микросекунды на вызов функции в Chromium (одну десятую в Firefox).
2. В вебпаке есть небольшой бутстрап, управляющий инициализацией и загрузкой модулей.
Rollup не использует обертки, а просто сбрасывает код всех модулей в одну область видимости.
В Webpack есть аналогичная оптимизация, но она работает не со всеми модулями.
Результаты исследования
Я надеюсь, что после прочтения этой статьи многие проверят свои системы сборки и удостоверятся, что они используют все возможные методы для наилучшего сжатия.Это быстро и легко.
Сначала правильно настройте комбинацию TypeScript и Babel. Пусть каждый компонент сборки занимается своим делом: один проверяет типы, а второй отвечает за преобразование в устаревшие стандарты.
Во-вторых, при использовании ES5 вы можете изменить минификатор обратно на UglifyJS, но помните, что он больше не поддерживается.
В-третьих, для сборки предпочтительнее выбирать Rollup. Однако это возможно не во всех случаях из-за отсутствия некоторых плагинов.
После сборки не забудьте проверить работоспособность функциональными тестами.
Если у вас их нет, самое время начать их писать.
В опросе могут участвовать только зарегистрированные пользователи.
Войти , Пожалуйста.
Как вы собираете свои проекты 9,09% накопительный пакет 28 84,74% веб-пакет 261 18,18% gulp 56 3,25% хрюканье 10 3,9% самописное решение 12 Проголосовали 308 пользователей.
73 пользователя воздержались.
Теги: #Исследования и прогнозы в ИТ #Разработка сайтов #JavaScript #оптимизация #webpack #Сжатие данных #сборка #роллап
-
Какой Ноутбук Предпочитает Хабра-Сообщество?
19 Oct, 24 -
Комментарии От Li.ru В Вашем Блоге
19 Oct, 24 -
У Каких Брендов Больше Всего «Друзей»?
19 Oct, 24