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

Как безопасно устанавливать и обновлять зависимости в JavaScript

31 января 2025
20 минут
эксперт информационной безопасности в Start X
Андрей Жаркевич
автор, дипломированный айтишник, люблю объяснять сложное простыми словами
Никита Барышников
автор, дипломиро­ванный айтишник, люблю объяснять сложное простыми словами
Никита Барышников
эксперт информационной безопасности в Start X
Андрей Жаркевич
Обучение навыкам безопасного поведения

Что такое менеджеры пакетов и зачем они нужны

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

Менеджеры пакетов, такие как npm и Yarn, автоматизируют эту работу и помогают:

  • Устанавливать библиотеки в проект с помощью одной команды.
  • Управлять версиями библиотек и их обновлением.
  • Отслеживать зависимости: если одной библиотеке требуется другая, менеджер установит ее автоматически — это называется транзитивными зависимостями.
  • Хранить данные о зависимостях в специальном конфигурационном файле package.json.
  • Гарантировать стабильность кода с помощью специальных lock-файлов package-lock.json или yarn. lock, которые фиксируют точные версии.

Чаще всего для управления пакетами в JavaScript используют npm. Этот инструмент поставляется вместе с Node. js и считается стандартом для большинства проектов на JavaScript.

Npm управляет самым большим в мире реестром JS-пакетов. Сейчас в нем зарегистрированы миллионы библиотек и инструментов для любых задач, от небольших утилит, — например, lodash, — до крупных фреймворков, таких как Angular, React или Vue
Скачайте карту знаний и навыков по безопасной разработке
В ней — 13 уязвимостей и технологий, которые нужно знать разработчику, чтобы писать безопасный код

Как устанавливать зависимости при помощи npm

Все, что касается зависимостей, фиксируется в специальном файле проекта — package.json. Чтобы создать package. json, используйте в терминале эту команду:
npm init
Добавить библиотеку или модуль в проект поможет такая команда:
npm install <название_пакета>
После ее выполнения пакет скачается из официального реестра npm и установится в папку node_modules вашего проекта. Также пакет добавится в раздел «dependencies» файла package.json.

В файл package. json добавится примерно такая строка:
"dependencies": {
  "lodash": "^4.17.21"
}
Локальная и глобальная установка

Локальная установка означает, что библиотека появится только внутри текущего проекта. Когда вы используете команду npm install, пакеты устанавливаются локально.

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

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

Для глобальной установки добавьте к команде флаг -g:
npm install -g <название_пакета>
Установка специфичной версии пакета

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

Чтобы установить специфичную версию пакета, укажите ее в команде:
npm install <название_пакета>@<версия>
На практике это выглядит так:
npm install lodash@4.17.10
Добавление зависимостей в package. json

В файл package. json зависимости можно добавить в разные разделы, в зависимости от их назначения.

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

Например, мы устанавливаем библиотеку axios:
npm install axios
В package. json видим:
"dependencies": {
  "axios": "^1.3.7"
}
devDependencies — зависимости, которые нужны только на этапе разработки, например, тестовые библиотеки, сборщики, линтеры.

Чтобы установить пакет в devDependencies, используйте флаг --save-dev:
npm install jest --save-dev
Или короткий -D:
npm install jest -D
Теперь в package. json пакет появится в разделе devDependencies:
"devDependencies": {
  "jest": "^29.2.1"
}
Чтобы увидеть список всех установленных пакетов и их версии, используйте эту команду:
npm list

Как обновлять зависимости с помощью npm

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

С помощью npm обновлять зависимости легко и удобно. Npm использует семантическое версионирование, которое делит номер версии на три компонента:

  • MAJOR: 1.0.0 2.0.0. Указывает на серьезные изменения, которые могут быть несовместимы с предыдущими версиями.
  • MINOR: 1.0.0 1.1.0. Добавляет новые функции или улучшения без нарушения совместимости.
  • PATCH: 1.0.0 1.0.1. Исправляет баги и улучшает стабильность без добавления новых функций.

В package. json зависимости обычно указываются с диапазоном версий, например:

  • ^1.0.0. Означает, что можно обновляться до новых MINOR и PATCH-версий, но не до MAJOR.
  • ~1.0.0. Показывает, что можно обновляться только до новых PATCH-версий.
  • 1.0.0. Фиксирует конкретную версию.

Обновление одного пакета

Если вы хотите обновить конкретный пакет до последней версии, выполните эту команду:
npm update <название_пакета>
Например, это может выглядеть так:
npm update lodash
Команда update обновит библиотеку до самой последней доступной версии в рамках указанного диапазона. Например, если указана «^4.0.0», библиотека обновится до версии 4.x.x, но не до 5.x.x.

Обновление всех пакетов

Чтобы обновить все пакеты проекта в рамках допустимых версий, выполните такую команду:
npm update
Команда пройдется по всем пакетам из файла package. json и обновит их до максимально допустимых версий, указанных в диапазонах.

Обновление до последней версии

Иногда нужно установить самую последнюю версию пакета, даже если она выходит за пределы указанного диапазона, например, обновить пакет до новой MAJOR-версии. Для этого выполните:
npm install <название_пакета>@latest
Например, это может выглядеть так:
npm install lodash@latest
Команда установит последнюю версию указанного пакета и обновит запись в package.json.

Проверка доступных обновлений

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

  • Current — текущая установленная версия.
  • Wanted — последняя доступная версия в указанном диапазоне.
  • Latest — самая новая версия, даже если она не входит в указанный диапазон.

На практике это выглядит так:
Package    Current   Wanted   Latest   Location
lodash     4.17.15   4.17.21  5.0.0    my-project
express    4.15.0    4.15.5   5.0.0    my-project
В примере выше lodash можно обновить до 4.17.21 в рамках текущего диапазона, но для перехода на версию 5.0.0 потребуется обновление диапазона версий в package.json.

Express обновится до 4.15.5 автоматически, но 5.0.0 — это новый основной релиз, который потребует ручного вмешательства.

При обновлении, особенно до нового MAJOR-релиза, важно помнить, что непредсказуемые изменения могут плохо повлиять на ваш проект. Например, новые версии библиотек могут содержать дополнительные функции, в результате чего совместимость с другими библиотеками проекта будет нарушена. Помните это и после обновления убедитесь, что все работает корректно.

Как удалять зависимости

Иногда в процессе разработки проекта требуется удалить ненужные пакеты. Например, при смене библиотеки или удалении из кода неиспользуемых модулей.

Для удаления пакета выполните эту команду:
npm uninstall <название_пакета>
Например, это может выглядеть так:
npm uninstall lodash
Команда uninstall удаляет пакет из папки node_modules и запись о нем из файла package. json, а также обновляет файл package-lock.json.

Проверка неиспользуемых зависимостей

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

Для проверки неиспользуемых библиотек можно использовать depcheck — утилиту для сканирования проекта и поиска неиспользуемых пакетов.

Чтобы установить ее, введите в терминале:
npm install -g depcheck
Для проверки проекта введите в терминале название самой утилиты:
depcheck
После выполнения команды вы получите такой список:

  • Unused dependencies — пакеты, которые больше не используются.
  • Missing dependencies — пакеты, которые используются в коде, но отсутствуют в package.json.

Вот как это может выглядеть:
Unused dependencies
* lodash
* moment

Missing dependencies* react-dom
Полная переустановка пакетов

Чтобы выполнить полную переустановку пакетов, удалите папку node_modules и файл package-lock.json.

Команда для удаления выглядит так:
rm -rf node_modules package-lock.json
После удаления переустановите пакеты заново с помощью npm install. Это гарантирует, что в папке node_modules останутся только актуальные пакеты.

Телеграм-канал Start X

Подписаться
Наши разборы мошеннических схем поймет даже бабушка

Как работать с package-lock.json и чем он отличается от package.json

При работе с проектами на JavaScript и Node. js есть два файла, которые занимают центральное место в управлении зависимостями — package. json и package-lock.json. Эти файлы выполняют разные, но взаимодополняющие роли.

package.json — основной файл конфигурации вашего проекта. Он содержит информацию о проекте, название, версию, автора, скрипты, зависимости или пакеты, версии Node. js и другие метаданные.

Вот как может выглядеть файл package. json:
{
  "name": "my-awesome-project",
  "version": "1.0.0",
  "description": "Awesome project description",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "jest": "^29.0.0"
  }
}
package-lock.json — файл, который npm создает автоматически. В нем хранятся версии всех установленных пакетов, включая их транзитивные зависимости, то есть те, от которых зависят другие библиотеки. Файл гарантирует, что все пользователи проекта используют одинаковый набор зависимостей.

Вот пример структуры package-lock.json:
{
  "name": "my-awesome-project",
  "lockfileVersion": 2,
  "dependencies": {
    "express": {
      "version": "4.17.1",
      "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
      "integrity": "sha512-..."
    }
  }
}
Вот сравнение назначения и различий между package. json и package-lock.json:
Как работать с package-lock.json

Lock-файл создается автоматически при выполнении команды npm install, если его еще нет. Если он существует, то npm проверяет, синхронизирован ли package-lock.json с package.json. Если обнаружены изменения, например, изменились зависимости в package. json, lock-файл обновится автоматически.

Иногда нужно удалить package-lock.json, например, при существенных изменениях в зависимостях. Для этого введите в терминал команды:
rm package-lock.json
npm install
Они перегенерируют lock-файл с актуальными версиями пакетов.

Если вы работаете в команде, изменения в lock-файле могут привести к конфликтам при слиянии веток. Чтобы избежать проблем — пересоздайте зависимости с помощью таких команд:
rm -rf node_modules package-lock.json
npm install

Как безопасно управлять зависимостями

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

Используйте package-lock.json

Всегда добавляйте package-lock.json в систему контроля версий, например, в Git, и не редактируйте lock-файл вручную. Lock-файл фиксирует точные версии всех зависимостей и их вложенных пакетов. Это гарантирует, что сборка вашего проекта будет идентичной на всех устройствах, будь то ваша машина, сервер CI/CD или компьютер коллеги.

Минимизируйте количество зависимостей

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

Как минимизировать количество пакетов:

  • Устанавливайте только те зависимости, которые нужны для работы проекта.
  • Проверьте, можно ли выполнить задачу без внешнего пакета. Особенно это касается простых функций, таких как сортировка или работа с датами.
  • Используйте встроенные инструменты Node. js вместо сторонних библиотек, если это возможно, например, fs для работы с файлами.
  • Регулярно анализируйте список зависимостей и удаляйте неиспользуемые.

Разделяйте dependencies и devDependencies

Пакеты в разделе dependencies нужны для работы приложения в runtime, например, express. Пакеты в devDependencies используются только в процессе разработки: тестирование, сборка и другие задачи.

Для разделения используйте флаг --save-dev, чтобы добавлять пакет только в devDependencies:
npm install eslint --save-dev
После этого убедитесь, что в dependencies остались только те пакеты, которые нужны для конечного приложения.

Используйте команды npm audit и npm audit fix

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

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

Используйте npm audit fix, чтобы автоматически исправить проблемы:
npm audit fix
Команда обновляет уязвимые пакеты до безопасных версий, если это возможно без конфликтов.

Регулярно очищайте node_modules

Папка node_modules со временем разрастается, занимает большой объем и содержит ненужные файлы. Кроме того, при сбоях или конфликтных зависимостях может потребоваться ее удаление.

Чтобы удалить папку, введите эту команду:
rm -rf node_modules
Если сразу писать безопасный код — не придется откладывать релиз из-за проблем с безопасностью и тратить время на исправление уязвимостей. На платформе Start EDU на практике учим устранять уязвимости в коде в зависимости от стека технологий. Запишитесь на бесплатное демо, и наш эксперт расскажет, как Start EDU помогает продуктовым командам предотвращать уязвимости и сразу писать безопасный код.
Мужчина в кресле с ноутбуком

Подпишитесь на дайджест Start X

Еженедельная подборка материалов и аналитики про цифровые атаки на людей, технологии защиты, безопасность инфраструктуры и приложений
Нажимая кнопку «Отправить заявку» вы соглашаетесь с политикой обработки персональных данных.