Главная » Хабрахабр » Ещё один инструмент для проверки ваших npm зависимостей — wtfwith

Ещё один инструмент для проверки ваших npm зависимостей — wtfwith

Вы как-нибудь задумывались, сколько версий одной и той же библиотеки затягивает ваша клиентская или серверная сборка? Мне вот в какой-то момент стало интересно. Навскидку найти для этого готовый инструмент не получилось, а смотреть глазами package-lock слишком утомительно. Как мы знаем — в любой непонятной ситуации нужно писать свой npm пакет, поэтому я именно это и сделал… Дальше в посте я рассмотрю результат анализа живого проекта и сделаю пару спорных выводов.

Ну и никак нельзя обойтись без этой классической картинки:

Как работает

В общем-то никакого rocket science — берём package.json и package-lock.json и пробегаем по всем зависимостям, которые там есть, собирая идентичные модули или модули-форки. Форки, ясное дело, приходится прописывать руками, поэтому сейчас в них указан только lodash и undescore. Но вы всегда можете помочь и расширить этот список.

Как использовать

Модуль опубликован на npm, проще всего запускать при помощи npx, хотя никто не мешает вам установить его локально или даже глобально. Дальше буду рассматривать вариант с запуском через npx. Для примера возьму один свой старый проект, который по сути является монолитом на ноде (это было ещё до микросервисного бума, а распиливать его потом было лень и нецелесообразно).

npx wtfwith moduleName (например, npm wtfwith lodash) — проверяем количество вхождений какого-то определённого модуля, выводит результаты, если их больше двух. 1. Результат может быть, например, такой:

пример

npx wtfwith lodash
npx: installed 3 in 2.047s
Searching for lodash
Checking path /web/xxx/package-lock.json
Huston, we have a problem:

4. 30 versions of lodash:
- 2. 18. 2 from root, cheerio@0. 10. 0
- 3. 6. 1 from xmlbuilder@2. 0. 4
- 4. 15. 0 from twilio@3. 17. 0
- 4. 1. 4 from graphlib@2. 0. 1, sway@1. 17. 0
- 4. 211. 5 from aws-sdk@2. 2. 0, xmlbuilder@4. 1. 1, request-promise-core@1. 13. 1, requestretry@1. 2. 0
- lodash.assign:4. 2. 0 from ioredis@3. 2. 2
- lodash.bind:4. 2. 1 from ioredis@3. 5. 2
- lodash.clone:4. 2. 0 from ioredis@3. 5. 2
- lodash.clonedeep:4. 2. 0 from ioredis@3. 2. 2
- lodash.defaults:4. 2. 0 from ioredis@3. 5. 2
- lodash.difference:4. 2. 0 from ioredis@3. 4. 2
- lodash.flatten:4. 2. 0 from ioredis@3. 5. 2
- lodash.foreach:4. 2. 0 from ioredis@3. 4. 2
- lodash.get:4. 18. 2 from z-schema@3. 3. 4
- lodash.includes:4. 2. 0 from jsonwebtoken@8. 0. 1
- lodash.isboolean:3. 2. 3 from jsonwebtoken@8. 4. 1
- lodash.isempty:4. 2. 0 from ioredis@3. 5. 2
- lodash.isequal:4. 18. 0 from z-schema@3. 0. 4
- lodash.isinteger:4. 2. 4 from jsonwebtoken@8. 0. 1
- lodash.isnumber:3. 2. 3 from jsonwebtoken@8. 0. 1
- lodash.isplainobject:4. 2. 6 from jsonwebtoken@8. 0. 1
- lodash.isstring:4. 2. 1 from jsonwebtoken@8. 2. 1
- lodash.keys:4. 2. 0 from ioredis@3. 0. 2
- lodash.noop:3. 2. 1 from ioredis@3. 1. 2
- lodash.once:4. 2. 1 from jsonwebtoken@8. 2. 1
- lodash.partial:4. 2. 1 from ioredis@3. 4. 2
- lodash.pick:4. 2. 0 from ioredis@3. 2. 2
- lodash.sample:4. 2. 1 from ioredis@3. 2. 2
- lodash.shuffle:4. 2. 0 from ioredis@3. 3. 2
- lodash.values:4. 2. 0 from ioredis@3. 2

Advice: Sometimes it is good to make a fresh start: rm ./ -rf && git commit -am 'nevermore' && git push origin master

2. npx wtfwith everything (можно просто опустить аргумент и написать «npx wtfwith», но это уныло) — проверяет вообще все зависимости, которых больше, чем две версии. Может быть, например, такой результат:

Пример

npx wtfwith lodash
npx: installed 3 in 1.813s
Searching all strange things...
Checking path /web/xxx/package-lock.json
Huston, we have a problem:

30 versions of lodash:
// ну, это вы уже видели

2. 4 versions of punycode:
- 1. 1. 4 from dkim-signer@0. 3. 2
- 1. 10. 2 from url@0. 4. 3
- 1. 3. 1 from tough-cookie@2. 1. 3
- 2. 0. 0 from uri-js@3. 2

4. 4 versions of xmlbuilder:
- 0. 7. 2 from nodemailer@0. 0. 1, aws-sdk@2. 6. 5
- 2. 4. 4 from root, xml2js@0. 2. 8
- 4. 211. 1 from aws-sdk@2. 4. 0, xml2js@0. 0. 17
- 9. 15. 1 from twilio@3.

1. 3 versions of xmldom:
- 0. 10. 19 from xml-crypto@0. 1. 1
- 0. 6. 27 from pdf2json@0. 1. 2
- 0. 0. 7 from ws.js@2. 22

2. 3 versions of mime:
- 1. 2. 11 from mailcomposer@0. 4. 12
- 1. 8. 1 from superagent@3. 3. 0
- 2. 1 from root

4. 3 versions of sax:
- 0. 2. 2 from xml2js@0. 6. 6
- 0. 4. 1 from xml2js@0. 2. 8
- 1. 211. 1 from aws-sdk@2. 4. 0, xml2js@0. 17

4. 3 versions of uuid:
- 1. 1. 2 from root
- 3. 211. 0 from aws-sdk@2. 2. 0
- 3. 83. 1 from request@2. 85. 0, request@2. 13. 0, requestretry@1. 15. 0, twilio@3.

2. 3 versions of xml2js:
- 0. 7. 6 from nodemailer@0. 0. 1, aws-sdk@2. 4. 5
- 0. 211. 17 from aws-sdk@2. 4. 0
- 0. 8 from root

19. 3 versions of moment:
- 2. 15. 3 from twilio@3. 20. 0
- 2. 5. 1 from moment-timezone@0. 22. 14
- 2. 9. 1 from root, joi@4. 0. 0, moment-range@1. 4. 9, moment-timezone@0. 5. 0, moment-timezone@0. 15

0. 3 versions of readable-stream:
- 1. 0. 34 from match-stream@0. 4. 2, pullstream@0. 0. 1, slice-stream@1. 1. 0, unzip@0. 1. 11
- 1. 2. 14 from dicer@0. 3. 5, ftp@0. 8. 10, htmlparser2@3. 7. 3, nodemailer@0. 3. 1
- 2. 14. 3 from mysql@2. 8. 1, superagent@3.

Advice: What about lunch?

3. Так же можно указать опцию --dev — в случае, если вы, например, собираете бандл из дев зависимостей. Хотя для этого лучше использовать фронтовые инструменты для анализа бандлов. Пример использования показывать не буду, команда выглядит как npx wtfwith everything --dev, и вы можете себе примерно представить, какой там выходит ад.

Реальные примеры

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

express — как ни удивительно, ничего интересного не нашлось. 1.

gulp — нашлись всякие мелочи: 2.

смотрим?

4 versions of kind-of:
- 3.2.2 from is-accessor-descriptor@0.1.6, is-data-descriptor@0.1.4, is-number@3.0.0, make-iterator@1.0.0, object-copy@0.1.0, snapdragon-util@3.0.1, to-object-path@0.3.0
- 4.0.0 from has-values@1.0.0
- 5.1.0 from array-sort@1.0.0, class-utils@0.3.6, is-descriptor@0.1.6, default-compare@1.0.0, expand-brackets@2.1.4, snapdragon@0.8.2, static-extend@0.1.2
- 6.0.2 from braces@2.3.1, is-accessor-descriptor@1.0.0, is-data-descriptor@1.0.0, is-descriptor@1.0.2, micromatch@3.1.10, nanomatch@1.2.9, use@3.1.0

2. 3 versions of define-property:
- 0. 3. 5 from class-utils@0. 1. 6, expand-brackets@2. 1. 4, object-copy@0. 8. 0, snapdragon@0. 1. 2, static-extend@0. 0. 2
- 1. 11. 0 from base@0. 3. 2, braces@2. 0. 1, extglob@2. 1. 4, snapdragon-node@2. 0. 1
- 2. 1. 2 from micromatch@3. 2. 10, nanomatch@1. 0. 9, to-regex@3. 2

npm — довольно забавный результат:
3.

смотрим!

14 versions of lodash:
- 3.10.1 from cli-table2@0.2.0
- lodash._baseindexof:3.1.0 from root
- lodash._baseuniq:4.6.0 from root
- lodash._bindcallback:3.0.1 from root
- lodash._cacheindexof:3.0.2 from root
- lodash._createcache:3.1.2 from root
- lodash._createset:4.0.3 from lodash._baseuniq@4.6.0
- lodash._getnative:3.9.1 from root, lodash._createcache@3.1.2
- lodash._root:3.0.1 from lodash._baseuniq@4.6.0
- lodash.clonedeep:4.5.0 from root
- lodash.restparam:3.6.1 from root
- lodash.union:4.6.0 from root
- lodash.uniq:4.5.0 from root
- lodash.without:4.4.0 from root

3. 3 versions of mississippi:
- 1. 6. 1 from make-fetch-happen@2. 0. 0
- 2. 0. 0 from cacache@10. 0. 4
- 3. 6. 0 from root, pacote@7. 1

0. 3 versions of pump:
- 1. 3. 3 from mississippi@1. 0. 1
- 2. 0. 1 from mississippi@2. 4. 0, pumpify@1. 0. 0
- 3. 0. 0 from mississippi@3.

Как минимум, забавно, что npm явно пытается минимизировать использование лодаша, но его целиком затягивает одна из его зависимостей…

Todo

Проект писался за вечер на коленке, поэтому есть некоторые количество вещей, которые там не реализованы:

Нет работы с shrinkwrap файлом — но это не очень нужно, вы можете просто сгенерить package-lock для проверки;
2. 1. Тоже не очень критично, ведь есть nvm;
3. Поддерживается только node 6+. Опять же не слишком критично;
4. Не поддерживается лок файл от yarn. Наверняка есть некоторое количество багов и неточностей.

В общем, если вам актуален инструмент, то pull requests приветствуются.

Выводы

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

Из спорных рекомендаций:

Я бы не рекомендовал для заведомо бэковых модулей затягивать зависимости вроде лодаша кусками — всё равно кто-то наверняка затянет к себе полную версию библиотеки. 1. То есть, если вы обнаружили breaking change в какой-то своей зависимости, то хорошо бы зайти к автору пакета и сказать, что он неправ — этим вы сэкономите другим много усилий и терабайты места на дисках. Ну и не забывайте про семантическое версионирование — конечно, без точных ограничений версий всё может в какой-то момент сломаться, но это должно решаться фиксацией зависимостей в package-lock и взаимодействием между разработчиками, а не точными ограничениям.

Стоит периодически пробегать по своим зависимостям и смотреть, что в них есть подозрительного, а затем отписывать issues или делать pull requests в проблемные модули. 2.

Если вам близка проблема обновления зависимостей, то напоследок могу посоветовать несколько полезных инструментов:

npm-check-updates — быстро смотрим обновления версий пакетов, быстро их ставим. 1. snyk — проверка безопасности пакетов, про него я уже писал чуть раньше.
3. Только аккуратно!
2. В случае, если вы работаете с фронтом, то наверняка используете что-то вроде webpack-bundle-analyzer, который вам расскажет, что именно у вас вышло в результате. node security project — ещё один инструмент для проверки безопасности зависимостей, который можно считать родным для экосистемы, потому что его недавно приобрёл npm.
4. Так же полезно иметь всякие бейджики и CI интеграции, которые вам будут наглядно показывать и оповещать, если что-то устарело или стало небезопасным. Но я с фронтом не работаю, так что здесь внятных рекомендаций дать не могу.
5. Интеграций тоже много, и, если у вас opensource проект, то travis-ci может прогонять практичски любые проверки. Примеров бейджиков приводить не буду, их весьма много, и часть вы можете посмотреть на shields.io.

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

«Ваша игра скучная», или как поднять уже и так высокий Retention первого дня

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

Ускоряем bootstrap больших баз данных с помощью Kubernetes

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