КАК: Обновить сразу все пакеты npm в вашем проекте

Быстрый, легкий и легкий, хотя и потенциально рискованный способ 😅

Есть ли быстрый и простой способ обновить все пакеты npm в вашем проекте? да. Все работает так, как вы ожидаете? Не всегда.

Для тех, кто находится в лагере TL; DR;, напишите и выполните сценарий узла (источник ниже), чтобы переписать все версии, перечисленные в package.json.

Как я могу узнать, какие пакеты устарели?

npm outdated

Команда outdated выведет список всех устаревших пакетов 👍

Нет ли команды npm для их обновления?

npm update --save/--save-dev

да. Вот и все. Однако пока он будет обновлять только пакеты. Функция update уважает semver. Например, если у меня есть пакет версии 1.3.5, но последняя версия - 3.0.5, пакет обновится только до последней версии minor. В нашем примере 1.9.9 может быть самой высокой версией до 2.0.0.

Для этого есть веская причина. Новые основные версии могут содержать критические изменения, которые могут нарушить работу вашего проекта. Вы хотите избежать этого сценария. Ограниченная мощность npm update способствует обновлению вручную. В свою очередь, ручное обновление упрощает выявление виновника, если что-то сломается 👀

Так зачем мне тогда это делать?

Правильный вопрос.

Был ли когда-нибудь проект, к которому вы не прикасались какое-то время? А когда вы к нему вернулись, зависимости пакетов сильно устарели?

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

Что-то вроде следующего было бы идеально;

npm update --save/--save-dev -f

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

Как же тогда это сделать?

Решением может быть использование npm run scripts. Мы можем определить сценарий, назовем его update:packages. Этот сценарий выполняет сценарий узла, который стирает все определенные версии в нашем package.json файле. Затем он удаляет наши установленные модули узлов. Наконец, он обновляет их все, сохраняя новые версии в package.json.

“scripts”: {
  “update:packages”: “node wipe-dependencies.js &&
                      rm -rf node_modules && npm update --save-dev
                      && npm update --save”
},

Чтобы запустить это в командной строке;

npm run update:packages

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

Этот сценарий узла? wipe-dependencies.js?

Маленький 😎 Используя fs, прочтите наш package.json файл, измените содержимое и запишите их обратно в файл.

const fs = require('fs')
const wipeDependencies = () => {
  const file  = fs.readFileSync('package.json')
  const content = JSON.parse(file)
  for (const devDep in content.devDependencies) {
    content.devDependencies[devDep] = '*'
  }
  for (const dep in content.dependencies) {
    content.dependencies[dep] = '*'
  }
  fs.writeFileSync('package.json', JSON.stringify(content))
}
if (require.main === module) {
  wipeDependencies()
} else {
  module.exports = wipeDependencies
}

Сотрите номера версий, заменив их звездочкой.

Эта версия охватывает как devDependencies, так и dependencies. Вы можете изменить сценарий так, чтобы он обновлял только devDependencies. Это может быть менее рискованно для фактического результата вашего проекта с самого начала.

БОНУС: Обновляйте только пакеты в реестре npm

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

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

const fs = require('fs')
const wipeDependencies = () => {
  const file  = fs.readFileSync('package.json')
  const content = JSON.parse(file)
  for (var devDep in content.devDependencies) {
    if (!content.devDependencies[devDep].includes(git)) {
      content.devDependencies[devDep] = '*'
    }
  }
  for (var dep in content.dependencies) {
    if (!content.dependencies[dep].includes(git)) {
      content.dependencies[dep] = '*'
    }
  }
  fs.writeFileSync('package.json', JSON.stringify(content))
}
if (require.main === module) {
  wipeDependencies()
} else {
  module.exports = wipeDependencies
}

Это нормально. Но это не очень хорошо 👎 Он проверяет только конечные точки git. Если есть другие шаблоны, которые мы хотим добавить в будущем, они должны быть реализованы больше проверок.

Одно мы точно знаем: любой пакет в реестре npm будет соответствовать SemVer. Его номер версии в большинстве случаев будет содержать только числа и символы, такие как 15.0.0 или 3.21.2, которым предшествуют некоторые символы. Также есть случаи, когда версия может содержать строки предварительного выпуска, такие как alpha или beta.

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

const fs = require('fs')
const wipeDependencies = () => {
  const file  = fs.readFileSync('package.json')
  const content = JSON.parse(file)
  for (var devDep in content.devDependencies) {
    if (content.devDependencies[devDep].match(/\W+\d+.\d+.\d+-?((alpha|beta|rc)?.\d+)?/g)) {
      content.devDependencies[devDep] = '*';
    }
  }
  for (var dep in content.dependencies) {
    if (content.dependencies[dep].match(/\W+\d+.\d+.\d+-?((alpha|beta|rc)?.\d+)?/g)) {
      content.dependencies[dep] = '*';
    }
  }
  fs.writeFileSync('package.json', JSON.stringify(content))
}
if (require.main === module) {
  wipeDependencies()
} else {
  module.exports = wipeDependencies
}

Вот и все!

Быстрый и простой, хотя и рискованный способ обновить все npm пакеты в вашем проекте сразу.

Как всегда, любые вопросы или предложения, не стесняйтесь оставлять отзывы или твитнуть меня 🐦!