- PVSM.RU - https://www.pvsm.ru -

Возможно, вам не нужен Svelte, чтобы уменьшить ваш JavaScript

Сейчас популярно мнение, что текущие Javascript-фреймворки непомерно большие, а новый фреймворк Svelte [1] очень компактный. Поэтому всем нужно переходить на него, и проблема размера Javasctipt решится сама собой.

Недавно вышла статья "Хороший ли выбор Svelte для реализации виджета?" [2] с опытом реализации проекта с критичным размером бандла. Это отличный повод проверить обещания пиарщиков Svelte на реальном проекте.

Давайте его проанализируем!

Исходные данные

Рассматриваемый проект – это встраиваемый виджет, распространяется как монолитный Javascript-бандл общим размером в 71 Кб (c учётом gzip). Много это или мало? В статье "Цена JavaScript в 2019 году" [3] была рекомендация избегать бандлов больше 50-100 Кб. То есть текущий проект находится в жёлтой зоне, размер ещё приемлемый, но уже пора задуматься, о том как в него добавить новой функциональности, и при этом уместиться в верхний лимит в 100 Кб.

Теперь скачаем [4] этот скрипт, отформатируем его и посмотрим, что там интересного.

Настройки бандлера

Первое, что бросается в глаза при просмотре кода – повторение вот такого паттерна:

function (t, e, n) {
    t.exports = {
        // какой-то код
    }
}

Это очень похоже на CommonJS модуль. Однако в современных проектах рекомендуется [5] использовать ES-модули, потому что этот формат обеспечивает возможность для оптимизаций – Scope hoisting [6] и Tree-shaking [7]. В случае CommonJS-модулей, бандлеры оптимизировать их не могут и выдают больше кода на выходе.

Иногда ещё может получиться так, что вы используете ES-модули в своем коде, а бандл все равно выходит не оптимизирован. В этом случае полезно запустить webpack с флагом --display-optimization-bailout [8] и посмотреть, что пошло не так с оптимизациями.

Неправильно настроенный бандлер может разрушить всю "магию исчезновения" [9] Svelte, которая целиком основана на описанных выше оптимизациях, поэтому в случае ошибок в конфигурации к вам в бандл попадёт весь фреймворк целиком.

К сожалению, у меня нет доступа к исходному коду, поэтому посмотреть на их настройки не получится, но по моему опыту правильно настроенные оптимизации позволяют сократить бандл на 20%, сбросив 14 Кб из общего размера виджета.

Оптимизация ресурсов

Далее мы замечаем, что в бандл включены SVG и JPG изображения. Очень важно, чтобы для веба ресурсы были правильно оптимизированы и весили как можно меньше.

Начнем с SVG. Для его оптимизации есть инструмент SVGO [10], также доступна онлайн-версия [11].

Всего в бандле нашлось 7 svg-файлов общим весом в 10 Кб, и, по-видимому, разработчики не занимались их оптимизацией. Пропустив их через SVGO удалось уменьшить общий размер на 3 килобайта.

Теперь про JPG. Заметим, что картинки загружаются в блок размером 59х27 пикселей, а сами оригиналы 183x72. Избыточный размер, даже с учетом поддержки retina-экранов. Кроме того, есть шансы улучшить размер подбором более оптимальных форматов сжатия. Очень удобно это делать в веб-приложении https://squoosh.app/ [12], которое позволяет пережать изображения прямо в браузере с использованием различных кодеков. Применив его к картинкам из виджета, сокращаем их размер на треть, получая еще 7 килобайт экономии.

Чтобы не тратить время на оптимизацию каждого изображения вручную, рекомендуется добавить процесс оптимизации в свою сборку, SVGO [10] уже упоминался выше, а для растровых картинок есть imagemin [13].

Ненужный код

Теперь переходим к разбору собственно Javascript. Там встречается нетранспилированный ES6-код, а значит поддержка IE от разработчиков не требовалась. И это действительно хорошая стратегия уменьшить размер кода – по моим данным, использование ES6 сокращает размер кода на 7%. Если вам не нужно поддерживать Internet Explorer, это может оказаться очень хорошим подспорьем.

Далее обратим внимание на используемые библиотеки.

  • axios [14] – библиотека для http-запросов. Поскольку вопрос поддержки IE не стоит, авторы могли использовать нативное Fetch API, а не брать эту зависимость, которая весит 4 Кб.
  • process [15] – полифилл объекта process из Node.js. Обычно включение этой зависимости является следствием неправильной конфигурации webpack, который видит process.env.NODE_ENV, и добавляет полноразмерный полифилл для process вместо одного только объекта process.env. Избавление от этого модуля сэкономит нам еще 1 килобайт.
  • sentry [16] – трекинг пользователя. Не будем здесь обсуждать хорошо ли следить за пользователями, но посмотрим как избежать этих 17 килобайт в бандле.
    • Sentry предлагает вариант загружать скрипт с их CDN. Здесь этот вариант помог бы, потому что скрипт скорее всего уже загружен в кэш пользователя на других сайтах, и время загрузки страницы сократится.
    • Здесь ещё стоит объяснить, почему обычно не рекомендуется [17] загружать библиотеки с чужих CDN, а здесь это приемлемо. Дело в том, что библиотека предназначена для отправления данных на сервера Sentry. Поэтому у вас в любом случае есть зависимость от их сервиса, неважно загружаете ли вы скрипт со своего сервера или их CDN.

Code coverage

Еще полезно прогнать код через Code Coverage [18] из Chrome Devtools. Для этого виджета инструмент показывает, что 24% Javascript не используется. Это не обязательно означает, что весь неиспользуемый код можно удалить, возможно, он нужен для обработки ошибок и других пограничных случаев, но это хороший сигнал обратить на него внимание и подумать, а зачем этот код вообще нужен.

Итог

Итого, оптимизации позволили бы сократить размер этого виджета на 46 килобайт (более чем в 2 раза!)

  • 14 Кб – настройка бандлера
  • 10 Кб – оптимизация изображений
  • 22 Кб – Javascript-зависимости

Таким образом, мы видим, что на размер бандла влияет множество факторов, и эффект от использования Svelte примерно как от запивания гамбургера диетической колой – исключительно психологический. Реальная оптимизация требует внимания к деталям и контролю размера на выходе.

А если вы задумываетесь о переходе на Svelte ради уменьшения размера своего проекта – советую обратить внимание на пункты выше, возможно, если их исправить, то никуда переходить и не понадобится.

Автор: Борис Сердюк

Источник [19]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/353516

Ссылки в тексте:

[1] Svelte: https://svelte.dev

[2] "Хороший ли выбор Svelte для реализации виджета?": https://habr.com/en/company/citymobil/blog/504270/

[3] "Цена JavaScript в 2019 году": https://habr.com/en/company/ruvds/blog/459296/

[4] скачаем: https://widget.city-mobil.ru/bundle.js

[5] рекомендуется: https://webpack.js.org/api/module-methods/#es6-recommended

[6] Scope hoisting: https://medium.com/webpack/brief-introduction-to-scope-hoisting-in-webpack-8435084c171f

[7] Tree-shaking: https://webpack.js.org/guides/tree-shaking/

[8] --display-optimization-bailout: https://webpack.js.org/plugins/module-concatenation-plugin/#debugging-optimization-bailouts

[9] "магию исчезновения": https://habr.com/en/post/345028/

[10] SVGO: https://github.com/svg/svgo

[11] онлайн-версия: https://jakearchibald.github.io/svgomg/

[12] https://squoosh.app/: https://squoosh.app/

[13] imagemin: https://github.com/imagemin/imagemin

[14] axios: https://github.com/axios/axios

[15] process: https://github.com/defunctzombie/node-process

[16] sentry: https://docs.sentry.io/platforms/javascript/

[17] не рекомендуется: https://habr.com/en/company/ruvds/blog/483682/

[18] Code Coverage: https://developers.google.com/web/tools/chrome-devtools/coverage

[19] Источник: https://habr.com/ru/post/504612/?utm_source=habrahabr&utm_medium=rss&utm_campaign=504612