Пряжа в 4,7 раза быстрее, чем npm @ 4. Но в игру вошел новый игрок

После долгого ажиотажа npm наконец-то переработал NPM и выпустил V5. Пока мы ждали npm @ 5, мир менеджеров по зависимостям потрясла новинка - Yarn от Facebook. Согласно моей приблизительной методологии тестирования: Я обнаружил, что Yarn стабильно в 4,7 раза быстрее, чем npm @ 4.

Поэтому обязательно, чтобы я провел несколько тестов на Yarn и npm @ 5.

Методика тестирования

Как и в предыдущем посте, я использовал ExpressJS в качестве нашего тестового репозитория.

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

Вот пошаговое описание процесса:

#1

Обновите npm, установите ExpressJS Generator и создайте новый проект.

npm install npm@latest -g
mkdir speedTest && cd speedTest
npm i -g express-generator
express speedTest

#2

Создайте yarn.sh, yarn_no_cache.sh, npm.sh и npm_no_cache.sh

touch yarn.sh yarn_no_cache.sh npm.sh npm_no_cache.sh

Мы заполним их простыми операторами, чтобы удалить npm_modules, заблокировать файлы и установить наши пакеты.

Ах да - у npm теперь тоже есть файл блокировки. Подробнее об этом позже.

Мы рассматриваем по 2 условия для npm и Yarn - с кешем и без него. Таким образом, у нас всего 4 теста.

#!/usr/bin/env bash
# yarn.sh
cd myapp &&
rm -rf node_modules yarn.lock package-lock.json &&
/usr/bin/time -p yarn
# yarn_no_cache.sh
cd myapp &&
rm -rf node_modules yarn.lock package-lock.json &&
yarn cache clean && 
/usr/bin/time -p yarn
# npm.sh
cd myapp &&
rm -rf node_modules yarn.lock package-lock.json &&
/usr/bin/time -p npm i
# npm_no_cache.sh
cd myapp &&
rm -rf node_modules yarn.lock package-lock.json &&
npm cache clean --force && 
/usr/bin/time -p npm i

#3

Создайте speedTest.js

// speedTest.js
const { spawnSync } = require('child_process');
let times = [];
for (let i = 0; i < 1000; i++) {
    console.log(`Running iteration ${i+1}`);
    // chmod +x *.sh if you have trouble with permissions
    let ls = spawnSync('./yarn.sh'); // Change this to run different tests
 times.push(parseFloat(ls.output.toString('utf8').match(/^real(.*)$/gm)[0].split(/\s+/)[1]));
}
console.log("Average time for yarn (with cache) is ");
console.log(`${(times.reduce((a, b) => a + b)/times.length).toFixed(3)}s`);

Скрипт довольно простой

  1. Он запускает сценарии установки npm / yarn 1000 раз
  2. Помещает время, затраченное на каждую установку, в массив times []
  3. Рассчитывает среднее время и отображает его на консоли

#4

Запустите сценарий тестирования для каждого файла .sh.

node ./speedtest

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

Итак - кто победил?

На этот раз гонка намного ближе. Вот результаты:

Average time for 1000 yarn installs (with cache) is
5.796
Average time for 1000 yarn installs (with no cache) is
7.416
Average time for 1000 npm installs (with cache) is
9.714
Average time for 1000 npm installs (with no cache) is
10.369

Пряжа все еще быстрее. Но ненамного. npm @ 5 удалось на несколько порядков повысить производительность, что является немалой задачей.

Но разве это просто скорость?

Нет, новое обновление npm - это не только скорость. Вот некоторые другие функции (позаимствованы из блога npm):

  • Новая стандартизованная функция файла блокировки, предназначенная для совместимости между менеджерами пакетов (package-lock.json), а также новый формат и семантика для термоусадочной упаковки.
  • --save больше не нужен. Все установки будут сохранены по умолчанию. Вы можете предотвратить сохранение с помощью --no-save.
  • Установка каталога пакета теперь заканчивается созданием символической ссылки и делает все, что нужно, в том, что касается сохранения и установки из блокировки пакета. Если у вас есть монорепозиторий, это может упростить работу и, возможно, намного быстрее.
  • Сценарии preinstall уровня проекта (верхнего уровня) теперь выполняются раньше всего и могут изменять node_modules до того, как CLI прочитает их.
  • Были добавлены два новых скрипта, prepack и postpack, которые будут работать как на npm pack, так и на npm publish, но НЕ на npm install (без аргументов). В сочетании с тем фактом, что prepublishOnly запускается перед созданием архива, это должно завершить общую историю, касающуюся возни с вашим кодом перед публикацией.
  • Зависимости Git со сценариями prepare теперь будут иметь свои devDependencies, и их подготовительный сценарий выполняется, как если бы они были под npm pack.
  • Зависимости Git теперь поддерживают сопоставление на основе semver: npm install git://github.com/npm/npm#semver:^5
  • node-gyp теперь поддерживает node-gyp.cmd в Windows
  • npm больше не заполняет ваш экран всем установленным деревом. Вместо этого вы увидите сводный отчет об установке, который намного удобнее для вашей оболочки. Специально для крупных проектов: $ npm install npm added 125, removed 32, updated 148 and moved 5 packages in 5.032s.
  • --parseable и --json теперь более согласованно работают с различными командами, особенно с install и ls.
  • Отступы теперь обнаруживаются и сохраняются для package.json, package-lock.json и npm-shrinkwrap.json. Если блокировка пакета отсутствует, по умолчанию используется текущий отступ package.json.

Так что же в итоге?

С npm @ 5 npm снова в гонке с Yarn. Между ними больше нет явной разницы.

Я не вижу причин, почему, если вы используете Yarn, переключаться на npm или наоборот, если вы обновляетесь до v5.

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

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