dimhold.by
← Статьи

Граф npm за 15 лет. Он вырос до 4,45 миллиона пакетов, а один аккаунт по-прежнему достаёт до четверти из них

Есть картинка npm, которая сидит у меня в голове уже много лет. Это Software Galaxies Андрея Кащи: весь реестр, нарисованный облаком звёзд. Мне хотелось ту же картинку, но в движении, кадр на год, чтобы увидеть, как эта штука растёт. Его данные по npm заканчиваются снимком ноября 2020 года, так что пришлось строить свою.

Мнение у меня тоже было готово до того, как я что-то посчитал. В 2019 году Циммерманн с соавторами написали, что 20 аккаунтов мейнтейнеров достают больше чем до половины npm. Я всегда относил это к годам left-pad. С тех пор реестр вырос с неполного миллиона пакетов примерно до 4,5 миллиона и я решил, что власть расползлась вместе с ним. Я ни разу это не проверял, мне просто нравилось, как это звучит.

Как я считал

8 октября 2026 года эндпойнт репликации реестра отдал 4465309 имён пакетов. Скачать все было нереально, поэтому я взял случайную выборку из 30000 имён и скачал их полные документы. На каждый год с 2011 по 2026 я брал самую высокую по номеру версию из существовавших на 31 декабря этого года вместе с её dependencies. 2026 год обрезан по началу 8 октября. Дальше я шёл по этим зависимостям вниз, пока недостающих не осталось. В итоге понадобилось 98736 документов пакетов.

Для каждого числа ниже важны такие правила. Пакет существует в году, если у него есть версия с датой до среза. Ребро это одна строка в dependencies этой версии, без dev и peer зависимостей. Числа для всего реестра это выборка, умноженная на 4465309 / 30000. Сам счёт написан на голом Python 3.12. Раскладку гифки делал networkx 3.6, рисовал matplotlib 3.11, сжимал gifsicle 1.94.

Прежде чем этому верить, я сравнил результат со старыми статьями. У Циммерманна было 1,3 прямой зависимости на пакет в 2011 году и 2,8 в 2018, у меня 1,26 и 2,91. В статье Робинсона с соавторами 2026 года у 61,3 процента пакетов есть хотя бы 1 зависимость, у меня 60,7. Достаточно близко, чтобы идти дальше.

Анимированный граф случайной выборки пакетов npm, кадр на год с 2011 по 8 октября 2026. Зелёные точки это пакеты с зависимостями, серые во внешнем кольце пакеты без них, оранжевые кружки 400 самых используемых пакетов, синие линии рёбра к ним. Центр вырастает из нескольких точек в плотное облако вокруг lodash, chalk, react и axios, а в 2024 году справа внизу появляется отдельное скопление спама. Счётчик идёт от примерно 2800 пакетов до 4,45 миллиона, а доля, до которой достаёт первый аккаунт, от 16 до 25 процентов.
Кадр на год с состоянием на 31 декабря, последний на 8 октября 2026 года. Точки это выборка, числа в углу пересчитаны на весь реестр.

Узлы и рёбра

На конец 2011 года выборка даёт около 2800 пакетов и 3600 рёбер. На 8 октября 2026 года это 4,45 миллиона пакетов и 19,4 миллиона рёбер. До 2024 года рёбра каждый год растут быстрее узлов, это видели ещё Кикас с соавторами в 2017 году. В 2025 и 2026 годах наоборот.

пакеты npm и рёбра зависимостей на конец каждого года, логарифмическая шкала 1 тыс. 10 тыс. 100 тыс. 1 млн 10 млн 100 млн 3572 2828 2,44 млн 838 тыс. 8,12 млн 2,51 млн 16,1 млн 19,4 млн 4,45 млн 2024: рёбер вдвое больше рёбра пакеты 2011 2014 2017 2020 2023 2026
Оценка на весь реестр: счёт по выборке, умноженный на 4465309 / 30000. 2026 год обрезан началом 8 октября. Ранние годы стоят на немногих пакетах выборки: 19 в 2011 году и 104 в 2012.

Потом наступил 2024 год и я решил, что у меня баг. Рёбер за 1 год стало вдвое больше, с 8,1 миллиона до 16,1 миллиона, а пакетов прибавилось на 28 процентов. Среднее число зависимостей прыгнуло с 3,24 до 5,02.

Это был не баг. Пакетов, созданных в 2024 году, в выборке 4724 и на них приходится 53391 ребро, то есть 41 процент всех рёбер 2026 года. У 431 из них 20 и больше зависимостей и 81 процент их рёбер ведёт к другим пакетам, созданным в 2024 году или позже. Пакеты, на которые они ссылаются, называются вроде gain-pleasant-prepare и anywhere-dream. Я открыл тарболы этих 431, прочитать удалось 430. В 52 лежит tea.yaml, файл протокола вознаграждений tea.xyz. Среди 1376 пакетов, созданных в 2023 году и имеющих хотя бы 1 зависимость, таких не нашлось ни одного. Значит, часть этого накрутка ради наград того протокола, а остальное я объяснить не могу.

Нашёл я их неприятным способом. Докачка замыкания не заканчивалась. Проход за проходом не хватало от 16 до 18 имён, потому что cadutdudut_128 зависит от cadutdudut_127, тот от cadutdudut_126 и так далее. Я остановился на 15 нескачанных именах. 11 из них это следующее звено такой пронумерованной цепочки, остальные 4 висят на пакетах тех же месяцев, с марта по май 2024 года. Они немного меняют размеры замыканий у спама и больше ничего.

Кто держит граф

Сначала прямые рёбра. В 2015 году 100 самых используемых пакетов получали 43 процента всех рёбер выборки. В 2018 году было 34 процента, в 2023 году 28, в 2026 году 20. Часть последнего падения дал спам 2024 года, потому что его рёбра ведут друг к другу. И всё же по этой мерке моё мнение подтвердилось и граф расползся.

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

насколько граф сосредоточен, проценты рёбра к 100 самым используемым пакетам пакеты, до которых достаёт первый аккаунт 0% 20% 40% 60% 43% 34% 28% 20% 35% substack 33% isaacs 25% sindresorhus 2014 2016 2018 2020 2022 2024 2026
Охват аккаунта это число пакетов, которые через зависимости подтягивают версию, где этот аккаунт есть в списке мейнтейнеров. Делим на все пакеты, включая 39 процентов без зависимостей.

Первый по охвату аккаунт доставал до 35 процентов всех пакетов в 2015 году (substack), до 33 процентов в 2018 (isaacs) и до 25 процентов в 2026 (sindresorhus). Здесь все пакеты считаются вместе с теми 39 процентами, у которых зависимостей нет вообще и до которых не достанет никто. Среди пакетов хотя бы с 1 зависимостью с 2021 года каждый год хватает 2 аккаунтов на половину из них.

До половины всего, если брать аккаунты в том же жадном порядке, что у Циммерманна, достают 11 аккаунтов в 2018 году и 17 в 2026. Я бы не стал верить этим числам с точностью до единицы. Когда я разбил выборку на 2 половины, вышло 10 и 12 для 2018 года и 14 и 19 для 2026, так что честный ответ на сегодня “от 14 до 19”. Доля первого аккаунта устойчива, 25,0 и 25,5 процента на 2 половинах.

Мой счёт не совпадает с их счётом. Они брали весь реестр до апреля 2018 года, я выборку и самую высокую версию каждого пакета. Мои 11 за 2018 год против их 20 могут объясняться этой разницей и больше я бы в это не вчитывался.

Итого с 2015 года доля 100 главных пакетов в прямых рёбрах упала вдвое, а охват первого аккаунта снизился всего с 35 до 25 процентов. Четверть npm по-прежнему зависит от одного аккаунта. Некоторые из 17 аккаунтов вообще не люди: types стоит почти за каждым пакетом @types, а react-bot, судя по имени, релизный бот React.

Чего я не проверял

  • “Мейнтейнер” здесь это список в документе версии. Наличие в списке ничего не говорит о том, кто публикует, у кого включена 2FA и кто перешёл на trusted publishing.
  • Снятых и удалённых пакетов в реестре сегодня нет, поэтому ранние годы занижены. Насколько, я не знаю.
  • Одна версия на пакет на год, диапазон версий у родителя я не разрешал. Настоящая установка может подтянуть другую версию с другими зависимостями.
  • Одна случайная выборка, один прогон. Ранние годы стоят на очень немногих пакетах, 104 в 2012 году и 754 в 2014, поэтому из них я бы не вычитывал ничего, кроме тренда.

Я так и не понял, что делать с этими аккаунтами, а их от 14 до 19. Большинство из них люди, которые ничего плохого не сделали: они рано написали маленькие пакеты и от них теперь зависят все.