Хабрахабр

[Из песочницы] Избавляемся от дублей пакетов в бандлах

Существует много webpack пакетов находящих дубли в бандле, самый популярный из них duplicate-package-checker-webpack-plugin, но он требует пересборки проекта, а так как стояла задача автоматизировать подбор оптимальной версии пакетов, то и вовсе получилось свое альтернативное решение.

Ну или моя история как получилось уменьшить бандл на 15%, за несколько секунд.

боль

Публикуются они через lerna, соответственно перед каждой установкой или обновлением общих компонентов возникает вопрос, какую версию устанавливать. Как и во многих крупных команиях у которых есть огромная кодовая база, много единой логики, как следствие используем общие компоненты, публикуемые в свой npm репозиторий. Соответственно, всегда есть версии нескольких компонентов, которые лучше подходят друг к другу, так как не конкурируют зависимостями. lerna перепаблишивает все компоненты, которые используют публикуемый компонент (если версия до этого последняя была).

Из open source проектов подобным образом паблишиться nivo, вот их конфиг lerna.

И как их устранять? Как появляются тогда дубли зависимостей?

Предположим, у вас есть простой проект со следующим package.json:


}

Посмотрим, где используется @nivo/core:

npm list @nivo/core

54. Видим 4 копии @nivo/core (3 экземпляра 0. 53. 0 и 1 — 0. Но если мы поменяем минорную версию @nivo/core на 0. 0). 0, дубли устранятся. 54.

Текущий пример прост, но на практике, естественно зависимостей у каждого пакета больше, и еще нужно рассмотреть подзависимости дальше, что увеличивает сложность задачи.

И как-то очередной раз увидев огромный размер бандла, мне надоело вручную устранять дубли пакетов.

Ведь нужно обновить версию зависимости в package.json, установить новые зависимости, и после проверить исчезли ли дубли в билде, если нет — повторить, долго, в среднем минуты 3-4 на итерацию. Вообще правильно сразу обновлять пакеты до последней версии, но времени как всегда нет, чтобы менять мажорные версии, а в слепую подбирать перебором подходящий пакет долго и сложно.

Все это монотонно и требует внимательности, поэтому решил автоматизировать.

Хотелось бы узнать дубликаты без переустанавки зависимостей, и пересборки проекта, в идеале cli приложение выводящее варианты оптимизаций за 10 секунд и все существующие дубли в проекте.

Устранение дублей можно поделить на несколько подзадач, рассмотрим их по порядку.

Первая задача. Нужно смоделировать будующее дерево зависимостей бандла только по package.json, учитывая стандартный dedupe, быстро, не более чем за 100ms.

Решил использовать package-json для получения информации по пакетам и semver для сравнения различных версий.

В итоге получился npm пакет dependencies-tree-builder, шустро моделирующий дерево зависимостей бандла только по package.json.

Выделил в отдельный компонент, ибо может быть кто-нибудь переиспользует его в комбинаторных задач с package.json.

Вторая задача. Комбинаторная задача, эффективный перебор вариантов изменения зависимостей, и сравнение нескольких вариантов деревьев, ну и естественно выбор оптимального.

Надо было как-то сравнивать качественно получившиейся деревья, и пришлось позаимтвовать идею энтропии, как количественное измерение беспорядка, взял сумму экземпляров дублей (из примера выше она равна 3).

Так как работают по следующему принципу: создают проект с единственной зависимостью, устанавливают зависимоти, после измеряется суммарный вес папки. Было бы здорово еще учитывать веса пакетов (в КБ), но к сожалению, пакета который бы быстро работал с весами я не нашел, а те что есть работают примерно по пол минуты на пакет, к примеру package-size. В итоге, другого критерия, как количество экземляров дублей не придумал.

Перебором устраняются дубли эффектов, насколько это возможно, а так как эффекты устраняются, то и дубли в последствии тоже. Чтобы понять какой пакет нужно изменить, рассматриваются причины дублей, конкретее источник и эффект.

В итоге, получилось небольшое cli приложение ostap, рекомендующее оптимльные версии для уменьшения количества экземляров дублей в бандле.

Запускается просто указанием на package.json вашего проекта.

ostap ./package.json

Еще можно использовать для быстрого просмотра всех будующих дублей без пересборки проекта меняя лишь версии в package.json.

ostap ./package.json -s

По итогу, в моем проекте суммарный вес бандлов снизился на 15%.

То есть вместо копий зависимостей на каждой странице, единственная версия перешла в общий бандл для всех страниц, поэтому нужно оценивать суммарный вес бандлов по всем страницам. Если используете route-splitting, может показаться, что какие-то бандлы увеличились в весе, но возможно изменилось распределение компонентов.

И кому-то информация съэкономит время. Надеюсь, статья была полезной. Спасибо.

Еще раз ссылочки для удобства:

  • Пакет моделирующий деверо зависимостей бандла по package.json
    GutHub;
  • Оптимизатор зависимостей для устранения дублей в бандле
    GutHub.

Если есть интересные идеи пишите в issue на guthub'е, обсудим.

Поддержите пожалуйста проект звездочкой на GutHub.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть