company_banner

Дорога в ад JavaScript-зависимостей

Автор оригинала: Nikola Đuza
  • Перевод
Каждый JavaScript-проект начинается с благих намерений, заключающихся в том, что его создатели обещают себе не использовать слишком много NPM-пакетов в ходе его разработки. Но даже если разработчики прилагают немалые усилия к тому, чтобы сдержать это обещание, NPM-пакеты постепенно проникают в их проекты. Размер файла package.json со временем растёт. А с package-lock.json после установки зависимостей происходит настоящий ужас, выражающийся в добавлениях и удалениях пакетов, особенно заметных при очередном PR…



«Всё нормально», — говорит тимлид. Остальные члены команды согласно кивают. А что ещё делать-то? Нам всем хорошо от того, что экосистема JavaScript жива и здорова. Нам не надо каждый раз изобретать колесо и пытаться решать задачи, уже решённые сообществом опенсорса.

Предположим, вы собираетесь сделать блог и хотите воспользоваться Gatsby.js. Попытайтесь добавить этот генератор сайтов в зависимости своего проекта. А теперь — принимайте поздравления. Только что в вашем проекте оказалось 19000 дополнительных зависимостей. Это нормально? Насколько сложным может стать дерево JavaScript-зависимостей? Как дерево зависимостей превращается в ад? Давайте с этим разберёмся.

Что такое JavaScript-пакет?


В NPM (Node Package Manager, менеджер пакетов Node) хранится самый большой реестр пакетов в мире. Это — JavaScript-пакеты. NPM больше, чем RubyGems, PyPi и Maven вместе взятые. Этот вывод можно сделать на основе анализа данных проекта Module Counts, на котором отслеживается количество пакетов в популярных реестрах.


Данные о количестве пакетов в популярных реестрах

Можно, подумать, что на этом графике представлены очень большие объёмы кода. Так оно и есть. Для того чтобы превратить некий проект в NPM-пакет, у этого пакета должен быть файл package.json. Такой пакет можно отправить в реестр NPM.

Что такое package.json?


Вот какие задачи решает package.json:

  • В нём перечислены пакеты, от которых зависит ваш проект (это — список зависимостей проекта).
  • В нём, с использованием правил семантического версионирования, задаются версии пакетов-зависимостей, которыми может пользоваться ваш проект.
  • Он позволяет воспроизвести среду, необходимую для работы пакета, и, в результате, упрощает передачу проекта другим разработчикам.

Файл package.json можно представить себе как файл README, накачанный стероидами. Здесь можно описать зависимости своего пакета, тут можно писать скрипты, выполняющиеся при сборке и тестировании проекта. В этом же файле находятся сведения о версии проекта, задаваемые его разработчиком, и описание проекта. Нас особенно интересует возможность package.json по указанию зависимостей проекта.

Пожалуй, то, что в этом файле указывают зависимости проекта, выглядит несколько настораживающе. Представьте, что имеется пакет, зависящий от другого пакета, а этот другой пакет зависит от ещё одного пакета. Такая цепочка зависимостей может быть сколько угодно длинной. Именно по этой причине установка единственного пакета, Gatsby.js, означает оснащение проекта 19000 дополнительных зависимостей.

Типы зависимостей в package.json


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

  • dependencies — это обычные зависимости, функционал которых используется в проекте, и к которым обращаются из его кода.
  • devDependencies — это зависимости разработки. Например — библиотека prettier, используемая для форматирования кода.
  • peerDependencies — если зависимости записываются в этот раздел, разработчик пакета тем самым сообщает тому, кто будет его устанавливать, о том, что ему понадобится конкретная версия указанного в этом разделе пакета.
  • optionalDependencies — тут перечисляют необязательные зависимости, такие, невозможность установки которых не нарушит процесс установки пакета.
  • bundledDependencies — тут даётся перечень зависимостей, которые встроены в пакет. Встраивание применяется для сторонних библиотек, которых нет в NPM, или в тех случаях, когда разработчик хочет включить в проект некоторые другие свои проекты в виде модулей.

Цель существования файла package-lock.json


Все мы знаем о том, что файл package-lock.json, в ходе работы над проектом, постоянно претерпевает изменения. Что-то из него удаляется, что-то в него добавляется. Особенно это заметно при просмотре PR, содержащих обновлённую версию этого файла. Мы часто принимаем это как данность. Файл package-lock.json автоматически генерируется каждый раз, когда меняется файл package.json или папка node_modules. Это позволяет поддерживать содержимое дерева зависимостей в точности таким, каким оно было при установке зависимостей проекта. Это позволяет, при установке проекта, воспроизвести дерево зависимостей. Это решает проблему наличия разных версий одного и того же пакета у разных разработчиков.

Рассмотрим проект, в составе зависимостей которого есть React. Соответствующая запись имеется в package.json. Если взглянуть в файл package-lock.json этого проекта, то там можно увидеть примерно следующее:

    "react": {
      "version": "16.13.0",
      "resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz",
      "integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==",
      "requires": {
        "loose-envify": "^1.1.0",
        "object-assign": "^4.1.1",
        "prop-types": "^15.6.2"
      }
    }

Файл package-lock.json — это большой список зависимостей проекта. Здесь перечислены версии зависимостей, пути (URI) к модулям, хеши, используемые для проверки целостности модуля и пакетов, нужных этому модулю. Если почитать этот файл, там можно найти записи обо всех пакетах, которые нужны React. Именно здесь и находится настоящий ад зависимостей. Здесь описано всё, в чём нуждается проект.

Разбираемся с зависимостями Gatsby.js


Как же получается так, что, установив всего одну зависимость, мы добавляем в проект целых 19000 зависимостей? Всё дело в зависимостях зависимостей. Именно поэтому у нас есть то, что есть:

$ npm install --save gatsby

...

+ gatsby@2.19.28
added 1 package from 1 contributor, removed 9 packages, updated 10 packages and audited 19001 packages in 40.382s

Если взглянуть в package.json, там можно найти лишь одну зависимость. Но если посмотреть на package-lock.json, то окажется, что перед нами — почти 14-килобайтный монстр. Более подробный ответ о том, что значат все те строки кода, которые попадают в package-lock.json, можно найти в файле package.json в репозитории Gatsby.js. Тут имеется очень много прямых зависимостей, а именно, по подсчётам npm, 132. Если у каждой из этих зависимостей будет хотя бы ещё одна зависимость, то общее количество зависимостей проекта удвоится — и у него окажется 264 зависимости. Конечно, в реальном мире всё не так. У каждой прямой зависимости проекта есть больше, чем 1 собственная зависимость. В результате список зависимостей проекта оказывается очень длинным.

Например — поинтересуемся тем, сколько раз в качестве зависимости для других пакетов используется библиотека lodash:

$ npm ls lodash
example-js-package@1.0.0
└─┬ gatsby@2.19.28
  ├─┬ @babel/core@7.8.6
  │ ├─┬ @babel/generator@7.8.6
  │ │ └── lodash@4.17.15  deduped
  │ ├─┬ @babel/types@7.8.6
  │ │ └── lodash@4.17.15  deduped
  │ └── lodash@4.17.15  deduped
  ├─┬ @babel/traverse@7.8.6
  │ └── lodash@4.17.15  deduped
  ├─┬ @typescript-eslint/parser@2.22.0
  │ └─┬ @typescript-eslint/typescript-estree@2.22.0
  │   └── lodash@4.17.15  deduped
  ├─┬ babel-preset-gatsby@0.2.29
  │ └─┬ @babel/preset-env@7.8.6
  │   ├─┬ @babel/plugin-transform-block-scoping@7.8.3
  │   │ └── lodash@4.17.15  deduped
  │   ├─┬ @babel/plugin-transform-classes@7.8.6
  │   │ └─┬ @babel/helper-define-map@7.8.3
  │   │   └── lodash@4.17.15  deduped
  │   ├─┬ @babel/plugin-transform-modules-amd@7.8.3
  │   │ └─┬ @babel/helper-module-transforms@7.8.6
  │   │   └── lodash@4.17.15  deduped
  │   └─┬ @babel/plugin-transform-sticky-regex@7.8.3
  │     └─┬ @babel/helper-regex@7.8.3
  │       └── lodash@4.17.15  deduped
  ...

К нашему счастью, большинство этих зависимостей представлены одной и той же версией lodash. А при таком подходе в node_modules будет лишь одна папка библиотеки lodash. Правда, обычно всё не совсем так. Иногда разным пакетам нужны разные версии одного и того же пакета. Именно поэтому и появилось много шуток об огромных размерах папки node_modules. В нашем случае, правда, всё не так уж и плохо:

$ du -sh node_modules
200M    node_modules

200 мегабайт — это не так уж и плохо. Я видел, как размер этой папки легко доходит до 700 Мб. Если вам интересно узнать о том, какие модули занимают больше всего места — можете выполнить следующую команду:

$ du -sh ./node_modules/* | sort -nr | grep '\dM.*'
 17M    ./node_modules/rxjs
8.4M    ./node_modules/@types
7.4M    ./node_modules/core-js
6.8M    ./node_modules/@babel
5.4M    ./node_modules/gatsby
5.2M    ./node_modules/eslint
4.8M    ./node_modules/lodash
3.6M    ./node_modules/graphql-compose
3.6M    ./node_modules/@typescript-eslint
3.5M    ./node_modules/webpack
3.4M    ./node_modules/moment
3.3M    ./node_modules/webpack-dev-server
3.2M    ./node_modules/caniuse-lite
3.1M    ./node_modules/graphql
...

Да, rxjs — коварный пакет.

Вот простая команда, которая помогает уменьшить размер папки node_modules и упростить её структуру:

$ npm dedup
moved 1 package and audited 18701 packages in 4.622s

51 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

В ходе дедупликации npm пытается упростить структуру дерева зависимостей, находя зависимости, используемые другими зависимостями, и перемещая их так, чтобы организовать их совместное использование. Это относится к нашему примеру с lodash. Множество пакетов используют lodash @4.17.15, в результате для обеспечения их работоспособности достаточно установить эту версию библиотеки лишь один раз. Конечно, это — та ситуация, в которую мы попадаем с самого начала, только установив зависимости. Если в процессе работы над проектом в package.json добавляют новые зависимости, рекомендуется иногда вспоминать о команде npm dedup. Если вы используете менеджер пакетов yarn, там аналогичная команда выглядит как yarn dedupe. Но в ней, на самом деле, необходимости нет, так как оптимизация зависимостей выполняется автоматически, при выполнении команды yarn install.

Визуализация зависимостей


Интересовались графическим представлением зависимостей своего проекта? Если так — сформировать такое представление можно с помощью специальных инструментов. Рассмотрим некоторые из них.

Ниже показан результат визуализации зависимостей, полученный с помощью npm.anvaka.com/.


Визуализация зависимостей, выполняемая с помощью npm.anvaka.com

Тут можно видеть взаимосвязи пакетов-зависимостей проекта Gatsby.js. Результат получается похожим на огромную паутину. У проекта Gatsby.js так много зависимостей, что эта «паутина» чуть не «подвесила» мой браузер. Вот, если интересно, ссылка на эту схему. Она может быть представлена и в 3D-виде.

Вот визуализация, сделанная с помощью npm.broofa.com.


Фрагмент визуализации зависимостей, выполненной с помощью npm.broofa.com

Это похоже на блок-схему. Она, для Gatsby.js, получается очень сложной. Взглянуть на неё можно здесь. Элементы схемы можно раскрасить, основываясь на оценках с npms.io. На сайт можно загрузить собственный файл package.json.

Средство Package Phobia позволяет, до установки пакета, узнать о том, сколько места ему требуется.


Сведения о пакете, полученные с помощью Package Phobia

Здесь можно узнать о размере опубликованного пакета, и о том, какое место на диске он займёт после установки.

Итоги: с большой силой приходит большая ответственность


В итоге хочется сказать, что JavaScript и NPM — это замечательные инструменты. Очень хорошо то, что у современных разработчиков есть возможность пользоваться огромным набором зависимостей. Выполнить команду npm install для того чтобы избавить себя от написания пары строчек кода — это так легко, что иногда мы забываем о последствиях.

Сейчас, когда вы дочитали до этого места, у вас должно сложиться более полное понимание особенностей устройства деревьев зависимостей npm-проектов. Если вы добавляете в проект библиотеку, которая очень велика, или если вы просто исследуете зависимости своего проекта, вы всегда можете воспользоваться тем, что мы тут обсудили, и проанализировать зависимости.

Уважаемые читатели! Стремитесь ли вы к тому, чтобы пользоваться как можно меньшим количеством зависимостей в своих npm-проектах?

RUVDS.com
VDS/VPS-хостинг. Скидка 10% по коду HABR

Комментарии 53

    +7
    Самое забавное, что разработчики ничего не могут поделать ни с этим адом js-зависимостей в своём проекте, ни с этим постоянно меняющимся файлом package-lock.json. И скорее всего даже не осознают, что делает большая часть этих скачанных пакетов, не говоря уже о каком либо сознательном выборе определённых версий этих пакетов.
      0

      В целом могут, особенно если не использовать фреймворки. Но вот сроки…

        0

        Аж заснуть не могу, не знаю, что и поделать с этими зависимостями

          +2
          Поэтому они так и называются «зависимости». Потому что от них у разработчиков зависимость.
          0

          npx yarn-dedup (по памяти) тоже прилично дубликатов вычистить может и уменьшить время сборки и размер бандла немного. А на проекте на TS ещё и от некоторых ошибок типов избавить

            +4

            Не совсем понимаю, почему при установке пакета устанавливаются зависимости, которые нужны для его разработки? Разве установка пакета не должна подтягивать только его собранную версию + всякие README.md и так далее. Есть npmignore которые фильтрует файлы для npm, почему тогда при установке подтягиваются зависимости которые нужны только для разработки этого пакета ( если по факту, я не буду его собирать, а буду использовать собранный бандл этого пакета )

              0
              Потому что собранный бандл пакета обычно содержит только код самого пакета, без зависимостей
                0

                Я ведь говорю про пакеты, которые нужны для разработки. Зачем скачивать условный babel, если в пакете уже есть собранная версия js и по факту, мы не пересобираем пакет, а используем его бандл. Я вроде где-то слышал, что с пакетом должны скачиваться только зависимости из dependencies, но в реальности все как-то наоборот

                  +6
                  Да нет, devDependencies зависимостей не скачиваются.
                    0

                    В статье пишут, что при скачивании gastby качаются еще и остальные пакеты. Если посмотреть на package.json то там все зависимости в devDependencies, почему и зачем тогда они скачиваются? Щас лично проверил, что бы точно убедиться и установка yarn add gatsby качает еще и бабели, пакеты для тестов и так далее

                      +2
                      Вы смотрите не в тот package.json. Это общие пакеты для монорепозитория. Вот package.json конкретно пакета gatsby
                        +6
                        Щас лично проверил, что бы точно убедиться и установка yarn add gatsby качает еще и бабели

                        Потому что он их использует не для разработки, а в деле. Т.е. это НЕ devDependencies.

                  +4
                  Люто плюсую. Бесит неимоверно. Кому-то не хватает мозгов прописать files в package.json и мы получаем +100500 кб нафиг ненужного барахла
                    +4
                    раскройте пожалуйста тему
                      +3

                      если не указать явно список файлов (package.json/files), формирующих пакет, то по-умолчанию в пакет будут включены все файлы в каталоге. Например исходники не нужны при наличии уже собранного js файла.


                      Я лично разделаю package.json проекта и package.json пакета, формирующегося из проекта. В него попадает лишь необходимый минимум: собранный код, типы для TS, Readme.md. Также это даёт более явный контроль над зависимостями пакета.

                        +1
                        Например исходники не нужны при наличии уже собранного js файла.

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

                          +1

                          А для этого есть GitHub и ссылка в package.json/repository. Это не настолько частая необходимость, чтобы оправдать раздувание node_modules.

                            0

                            Для меня очень частая. Тут больше особенность самих npm/yarn — просто тупо делят зависимости на дев-билд (причём нет единого мнения в коммьюнити, что куда относится, куда входят зависимости для билда, например) без возможности указывать загружать исходники при наличии "бинарников" или нет.

                      –2
                      Бесит неимоверно. Кому-то не хватает мозгов прописать files в package.json...
                      А вам хватает мозгов зайти на гитхаб, создать issue или отправить pull request? Всё решаемо.
                        +1
                        Чего это вы так взбеленились? Это ваши модули? С чего вы взяли что я не создаю issue? Я на такое ругался еще со времен jquery плагинов и browserify, который этим то же страдал даже в большей степени.
                        К тому же, обычно лишние файлы не видно, нужно специально лезть в модули, что делается крайне редко. Замечать это начинаешь когда inodes заканчиваются и тормозит IDE. Вот тогда и подбешивает, смотришь на размеры папок и сносишь модули в старых проектах.
                          0
                          Чего это вы так взбеленились? Это ваши модули? С чего вы взяли что я не создаю issue?
                          Я просто задал вопрос в Вашей манере. Часто вижу, что люди могут только ругаться, не прилагая никаких усилий для исправления недочётов. Но Вы не такой, это радует.
                    +1

                    Ну а какая альтернатива-то? Чтоб каждая зависимость содержала свои костыли вместо lodash? Ну на бэкенде еще относительно пофиг, а на фронте раздутые бандлы как-то не алё.


                    Тут, конечно, корни растут из относительно бедной стандартной библиотеки языка, и она потихоньку растёт, но продукт-то надо релизить прямо сейчас...

                      +13

                      А я так и не понял, в чем проблема. Ну да, Gatsby требует кучу своих зависимостей. И хорошо, пусть требует. В мой package.json они не протекают, а в package-lock можно не смотреть, он вообще для чтения человеком не очень предназначен.

                        +1

                        Так всё просто — есть проблема с одинаковым окружением. Кстати, решение этой проблемы сделало docker таким популярным, например. Тут типа того — разные версии пакетов, иногда и минорно, могут иметь разное поведение. И единственный адекватный кейс — всегда устанавливать именно то окружением что задумывалось разработчиком, иначе это будет порождать пляски с бубном на продакшене и прочее такое. Это плохо, уж лучше пакетов побольше, но всё же стабильная работа.


                        Ну и вторая причина количества пакетов вообще — любовь к мелкой модульности без таскания целых библиотек. Более того — некоторые популярные библиотеки представляют цельную версию и к ней по модулю на каждую входящую функцию — чтобы разработчик мог взять только одну или несколько, а не тащить с собой 100500 функций ради использования лишь одной. Разве это плохо? Вроде как очень даже хорошо. Ну а то что на npm сайте так много модулей — ну и что, больше выбора наоборот же.


                        В общем какая-то злая статья без понимания механизмов почему так. Не, конечно некоторые разработчики некоторых пакетов могут лишнее таскать, качество пакетов может быть сомнительным, как и эффективность — но так то это и в любом другом бывает, будь то Ruby или .NET экосистема. А с общим механизмом пакетов всё вполне себе.

                          0
                          И единственный адекватный кейс — всегда устанавливать именно то окружением что задумывалось разработчиком

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

                          +1
                          > Если в процессе работы над проектом в package.json добавляют новые зависимости, рекомендуется иногда вспоминать о команде npm dedup

                          я надеюсь, у вас сборка для продакшена осуществляется с чистого листа, а не вот это вот все
                            0

                            В чём плюсы такого подхода? Неизвестные же версии могут установиться.

                            –3

                            Мне еще нравится, что при помощи webpack я не могу собрать оптимизированный bundle для node.js приложения. Это приводит к тому что вместо 200 килобайт, приложение под node.js весит 200 мегабайт. Это прям прекрасно.

                              0
                              Ну как бы, а что мешает разобраться?
                              image

                              Посмотрите что забивает бандл и найдите проблему
                                +1

                                Я пробовал, у меня с ходу не получилось. Там какие-то проблемы с тем что откуда читается, плюс nodejs отличается от web окружения. Хотите попробовать? Не ничего проще берете https://www.zigbee2mqtt.io/ и пытаетесь сделать из него рабочий бандл.

                                  0
                                  nodejs отличается от web окружения

                                  Большая часть моего кода собирается под nodejs. Отличия есть, но они мизерные. Сделайте минимальное демо проблемы и киньте в ЛС/сюда, подскажу. Вебпак весьма ожидаемо работает. Не идеален, но в основном(не встречал другого) предсказуем.
                                    0

                                    Легко. Вот файл. После сборки в банл не запускается вот эта строка
                                    https://github.com/Koenkk/zigbee2mqtt/blob/master/index.js#L5

                                      +1

                                      Да поясню почему именно этот. Хочется запихнуть на embedded платформу, а там 128 мегабайт NAND. Если еще nodejs я туда со скрипом но утрамбую, но вот уже 200 мегабайт под модули и прочее барахло места не сказать что есть.


                                      На вопрос "Эй чувак а чего ты туда вообще js потащил?" Спросите у всех кто IoT занимается. Там какая-то нездоровая тенденция лабать на JS.

                                    0

                                    А ну да поиск схожей проблемы дает знаете какой ответ? Дак вы соберите приложение в один js файл, а бандлы запакуйте в zip и распакуйте на сервере. Что-то такого я не ожидал.

                                  0
                                  А после добавления Gatsby.js и сборки в бандл попадают все зависимости? И сколько такой бандл весит и сколько мегобайт js должен «прожевать» браузер при открытии страницы?
                                    +3

                                    Проблема осложняется тем, что в npm-модуль обычно попадает куча лишних файлов.


                                    Например, возьмем vue. В папке dist у них лежит четырнадцать (!) вариантов собранного фреймворка общим весом 2.5мб с различными комбинациями вариантов: минифицированный\не минифицированный, c модулями CommonJS или ES Modules, для продакшена и нет. Рядом же есть папка source, в которой еще двести (!) файлов общим весом 500+ кб, чтобы можно было собрать все из исходников. Какой смысл поставлять одновременно и собранный вариант, и исходники для самостоятельной сборки? В некоторых подпапках также валяются системные файлы .DS_store, которые явно попали туда по недосмотру.


                                    В bootstrap все то же самое, но еще есть две смешные папки: dist/js и js/dist. В первой собран весь код JS (опять же, 4 варианта с минификацией и прочим), а во второй он разделен на модули.


                                    Но многие авторы вообще не парятся. Например, пакет promise-polyfill включает в себя: CHANGELOG.md, .editorconfig, .npmignore, .eslintrc.js, .travis.yml, а также тесты (тесты, Карл!) вместе с конфигом karma.conf.js. Зачем все это должно поставляться конечному потребителю?


                                    И к сожалению, даже если исключить безалаберность разработчиков модулей и почистить весь хлам, более фундаментальная проблема разобщенности экосистемы останется. Очевидно, что авторы хотят сделать свои модули легко интегрируемыми в большинство проектов, но число комбинаций технологических стеков растет в астрономической прогрессии. В результате страдают все — одни от того, что конкретно их комбинация не поддерживается; другие — что помимо поддержки для их комбинации им приходится скачивать файлы для пары дюжин других.

                                      0

                                      Если это действительно является проблемой (например, не хочется тащить лишние файлы в прод), то можно воспользоваться modclean.

                                        +1

                                        Тем не менее, они валяются на диске и тратят время при билде на CI. И нет абсолютно никакой уважительной причины, почему это так.

                                          0

                                          А какие у вас уважительные причины чего-то требовать от людей, которые бесплатно выложили в общий доступ полезные инструменты?

                                            +2

                                            Я жалуюсь не на конкретных людей, а на экосистему в целом. Теория разбитых окон в действии — когда вокруг все вокруг на тройку, какой резон стараться сделать хорошо?


                                            В основном я пишу на C#, поэтому есть с чем сравнить. Сама экосистема не так фрагментирована, есть богатая стандартная библиотека (поэтому нет нужды в вещах типа left-pad), nuget'ы практически всегда достаточно просто установить и все заработает, без мусора и доработки напильником. И все это настолько же открытое и бесплатное.

                                        0
                                        а как вам мешают лежащие в папке dist вариации сборки, кроме как кушают место и время однократно, при инсталле?
                                          +1

                                          Место они кушают не однократно, а по количеству проектов, плюс также валяются в локальном кеше npm. И время они кушают не однократно, а при каждом билде на CI, т.к. он делается в чистой папке.

                                            +2
                                            Насчёт места — посмотрите в сторону pnpm
                                        0
                                        А теперь — принимайте поздравления. Только что в вашем проекте оказалось 19000 дополнительных зависимостей. Это нормально? Насколько сложным может стать дерево JavaScript-зависимостей? Как дерево зависимостей превращается в ад? Давайте с этим разберёмся.


                                        Собственно, я не увидел постановки проблемы.

                                        В чём конкретно заключаются претензии к разросшемуся дереву зависимостей? Чем это грозит? В чём заключаются экономические потери для проекта, прямые или косвенные?

                                        Или речь уклончиво ведётся к размеру финального бандла, в который гипотетически может попасть то, что не должно? В этом случае грамотный импорт и tree shaking изрядно спасает ситуацию.
                                            +1
                                            как вы понимаете, варианта два:
                                            — писать всё самому
                                            — доверять разработчикам пакета и их решению в выборе используемых зависимостей

                                            Частично проблему с уязвимостями помогает понять audit, но соглашусь — не панацея.

                                            Сокращение же количества зависимостей с 20 000 до 10 000 даёт, мягко говоря, опосредованное чувство защищённости. Оптимизация есть хорошо, но конкретно эта — не о безопасности, лишние телодвижения и полумеры.
                                          –5

                                          Меня оскорбляет то, что на первом изображении Vue ниже чем Angular и React

                                            0
                                            Спасибо за статью
                                              0
                                              RxJS, конечно, удивил. Он же проде как рекламируется как легкий?
                                                +1

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

                                                  +1
                                                  У вас опечатка в README:

                                                  Why should I cate about my package size?
                                                  +1
                                                  Сам разрабатываю на PHP, но без NPM, разумеется обойтись не могу. Если сравнивать с PHP Composer, то налицо разница в концепциях:

                                                  • В PHP каждый пакет в vendors может встречаться только однажды. Хочешь странного — извращайся на свой страх и риск (вариантов извращений немало — есть из чего выбрать). Это иногда заставляет страдать, потому что использовать конкретную версию конкретной библиотеки не получается, даже если очень срочно надо — не решается уравнение по разрешению зависимостей и всё тут. Но, с другой стороны — это всегда осознанные проблемы, которые нельзя «замести под ковёр» ни на каком уровне зависимостей. И на общем числе зависимостей это сказывается зело позитивно: несколько раз подумаешь, с кем завязывать отношения, а без кого можно и обойтись.
                                                  • В npm один и тот же пакет может существовать в нескольких версиях. Не просто один пакет в нескольких местах, а именно несколько версий одного пакета. Это делает жизнь добавление пакетов проще, но… гораздо непредсказуемее. И технический долг неровным слоем размазывается на всю экосистему. В какой-то момент это просто обязано вынудить сообщество к каким-то эволюционным или революционным изменениям в отношениях конфигурации зависимостей.


                                                  Что касается окружений, то в PHP есть только два варианта зависимостей: prod и dev. Это уменьшает число комбинаций.

                                                  Про содержимое продуктового пакета: к этому в PHP начинают относиться более строго всё большее количество крупных разработчиков. Продуктовые пакеты symfony, например, похудели очень ощутимо. Многие рецепты вполне универсальные и могут быть заимствованы напрямую в npm best practices.

                                                  Не знаю, насколько надумана проблема нескольких сборок под разные архитектуры, языки, размер (минифицированные или нет) и т.п. Всегда считал, что правильно не хранить вычисляемые вещи в репо, а возложить эту задачу на registry — собирать отдельные артефакты под каждую комбинацию. И сформулировать соглашение об именовании этих артефактов, с учётом версионирования. Наверняка, на это тоже есть какие-то причины… но выглядит костыльно.

                                                  В общем, имхо, если следующие версии npm явно запретят некоторые вольности, то с этим адом вполне можно будет совладать. И разработка от этого только выиграет.
                                                    0
                                                    Я ожидал от этой статьи скорее «почему это плохо». Например, что ошибка в одном из очень используемых пакетов приведет к падению огромного количества проектов при обновлении. Или, например, долгую компиляцию на серверной стороне (или долгое выкачивание зависимостей, что сильно осложняет CI/CD). Или необходимость выкачивать в браузере большое количество не полностью используемых скриптов… И все это со ссылками конкретно на ваш случай…

                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                    Самое читаемое