Главная / Статьи / Что на самом деле делает npm install: реестр, package.json и файлы блокировки

Что на самом деле делает npm install: реестр, package.json и файлы блокировки

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

1605 слов

Почти каждый проект на JavaScript, независимо от того, работает ли он с Node.js, React или Next.js, начинается с одного и того же командного приказа, и многие разработчики выполняют его ежедневно, не имея четкого представления о том, что он делает. Знание того, откуда берутся пакеты, как npm решает, что установить, и для чего предназначены файлы package.json, package-lock.json и node_modules, помогает более легко отлаживать проблемы с установкой. В этом руководстве рассматриваются все аспекты, от первой установки до публикации собственного пакета.

Команды, которые используют все

Наиболее распространенный способ — установка всего, что уже указано в проекте:

npm install

Не менее часто используется добавление библиотеки по ее названию, например веб-фреймворка Express:

npm install express

или HTTP-клиента Axios:

npm install axios

За этими однострочными командами скрывается несколько вопросов. Откуда загружается код? Как npm узнает, от чего зависит проект? Для чего существует package.json? И почему папка node_modules становится такой большой?

Что такое npm

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

Можно представить его как общественную библиотеку кода. Предположим, что сервер Node.js нуждается в HTTP-сервере. Вместо того чтобы с нуля создавать механизмы маршрутизации и промежуточные компоненты, достаточно добавить библиотеку Express:

npm install express

Нужно вызвать другие API? Добавьте HTTP-клиент:

npm install axios

Проверка входящих данных согласно схеме осуществляется с помощью библиотеки Zod:

npm install zod

Bcrypt отвечает за хеширование паролей:

npm install bcrypt

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

Экосистема, а не просто команда

Новички часто воспринимают npm как просто слово, введенное в терминал. На самом деле это название охватывает несколько взаимодействующих компонентов:

  • Реестр npm: общедоступный сервис, где пакеты публикуются и загружаются.
  • CLI npm: инструмент командной строки, который взаимодействует с реестром и управляет зависимостями.
  • Пакеты: сами повторно используемые единицы кода.
  • package.json: манифест, описывающий ваш проект и зависимости от него.
  • Публичные пакеты бесплатны: вы можете установить любой публичный пакет без создания учетной записи. Такие низкие барьеры способствовали распространению JavaScript с открытым исходным кодом по всему миру. Учетная запись нужна только для публикации.

    Что происходит при выполнении команды npm install

    Возьмем проект, в котором используется Express:

    npm install express
    

    В общих чертах:

    1. npm находит пакет в реестре и выбирает версию, соответствующую указанному диапазону (последнюю, если он не указан).
    2. Он разрешает зависимости самого пакета и его внутренние зависимости, формируя полную структуру.
    3. Он загружает все, что еще не находится в кэше, и сохраняет его в папке node_modules.
  • Он записывает зависимости в package.json и точную структуру решённых зависимостей в package-lock.json.
  • Именно так один короткий командный приказ позволяет включить целую структуру функционала.

    package.json: манифест проекта

    В центре каждого проекта Node.js находится один файл:

    package.json
    

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

    {
      "name": "my-project",
      "version": "1.0.0",
      "description": "My Node.js application",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "dependencies": {
        "express": "^5.1.0"
      }
    }
    

    name

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

    "name": "my-project"
    

    version

    version содержит текущую версию пакета.

    "version": "1.0.0"
    

    Это особенно важно при публикации. npm использует семантическую версионирование (MAJOR.MINOR.PATCH): кардинальные изменения увеличивают основное число, совместимые функции — вторичное, а исправления — патч-номер.

    Описание

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

    "description": "My Node.js application"
    

    Скрипты

    scripts определяет именованные сокращения для часто используемых команд. Здесь start запускает основной файл проекта:

    "scripts": {
      "start": "node index.js"
    }
    

    Без него придется вводить полную команду:

    node index.js
    

    С ним это делается так же:

    npm start
    

    Ключевое требование — единообразие: каждый участник и каждая задача CI выполняют одну и ту же команду с определенным именем. Собственные имена, такие как build, запускаются с помощью команды npm run build.

    Зависимости: от чего зависит ваш проект

    Представьте платформу для доставки еды. В её бэкенде могут использоваться:

    • Express для API
    • Zod для валидации
    • bcrypt для хеширования паролей
    • библиотека JSON Web Token для аутентификации
    • Mongoose для работы с MongoDB

    Каждый из этих инструментов является зависимостью. Когда вы устанавливаете одну из них:

    npm install express
    

    npm добавляет запись в package.json:

    "dependencies": {
      "express": "^5.1.0"
    }
    

    Знак вверху в ^5.1.0 обозначает диапазон: принимаются все последующие версии 5.x, но не 6.0.0. Эта запись сообщает всем, кто читает проект, что для его работы необходим Express. Инструменты, нужные только во время разработки, такие как тест-запускатели, помещаются в devDependencies с помощью команды npm install --save-dev.

    Почему одна команда может использоваться всей командой

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

    npm install
    

    npm считывает указанные зависимости и устанавливает их все. Именно возможность воссоздания рабочей среды на основе описания делает менеджеры пакетов неотъемлемыми инструментами.

    node_modules: место хранения установленного кода

    После установки появляется новая папка:

    node_modules/
    

    В ней находятся пакеты, которые вы запросили, а также все зависимости от них, поэтому размер этой папки бывает велик. Типичная структура:

    my-project/
    │
    ├── node_modules/
    ├── package.json
    ├── package-lock.json
    └── index.js
    

    Не добавляйте папку node_modules в Git. Она большая, может содержать версии кода для конкретных платформ, и её всегда можно воссоздать. Добавьте её в файл .gitignore и сохраняйте вместо неё эти файлы:

    package.json
    package-lock.json
    

    Затем любой другой человек может запустить:

    npm install
    

    и получить те же самые зависимости.

    package-lock.json: точная запись состава

    Рядом с описанием проекта находится ещё один файл:

    package-lock.json
    

    Почему оба файла? Краткий ответ:

    • package.json указывает, что требуется проекту, обычно в виде диапазонов версий.
    • package-lock.json фиксирует точно то, что было установлено: каждая версия пакета во всей структуре проекта, а также хэши целостности.

    Поскольку диапазоны могут со временем совпадать с более новыми версиями, файл lockfile обеспечивает одинаковые версии на ноутбуках, у коллег и в системах CI. Сохраняйте его, а в CI предпочитайте использовать npm ci, который устанавливает пакеты строго согласно данным lockfile.

    Команды npm, которые стоит знать

    Добавление пакета:

    npm install express
    

    Установка всего, что указано в проекте:

    npm install
    

    Удаление пакета из node_modules и package.json:

    npm uninstall express
    

    Обновление пакетов до самых новых версий, разрешенных диапазонами (без перехода на новую мажорную версию):

    npm update
    

    Вывести версию npm:

    npm -v
    

    Вывести версию Node.js:

    node -v
    

    Показать аккаунт npm, под которым вы вошли:

    npm whoami
    

    От потребителя к публикатору

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

    npm install your-package
    

    Этот цикл поддерживает жизнедеятельность открытого кода: вы развиваете чужие работы, создаёте собственные и делитесь ими с другими.

    Шаги публикации по порядку

    Вам нужен аккаунт npm. Войдите в него из терминала:

    npm login
    

    Подтвердите, какой аккаунт находится в активном состоянии:

    npm whoami
    

    Перейдите в папку проекта:

    cd myproject
    

    Убедитесь, что в проекте есть действительный манифест с уникальным name и version:

    package.json
    

    Затем опубликуйте проект:

    npm publish
    

    Теперь этот пакет доступен всем. Два совета: сначала выполните команду npm pack --dry-run, чтобы узнать, какие файлы будут включены, и всегда обновляйте version при каждой публикации, поскольку опубликованная версия не может быть использована повторно. Ознакомьтесь с текущей документацией npm по требованиям к безопасности аккаунтов, таким как двухфакторная аутентификация.

    Как все взаимосвязано

    Весь процесс выглядит следующим образом:

    Developer
        ↓
    npm install
        ↓
    npm Registry
        ↓
    Package + Dependencies
        ↓
    node_modules
        ↓
    package.json
        ↓
    Your Application
    

    Вы выполняете команду, CLI загружает пакеты из реестра, код попадает в папку node_modules, манифест и файл lockfile фиксируют эти данные, а ваше приложение импортирует его. Именно эта цепочка позволяет разработчикам эффективно повторно использовать, управлять, делиться и публиковать код.

    Основные выводы

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

    npm install
    

    Система становится более понятной для анализа. JavaScript предоставляет язык, Node.js — среду выполнения, а npm — экосистему для обмена кодом. На практике:

    • package.json описывает намерения; package-lock.json фиксирует реальное состояние. Сохраняйте оба файла.
    • Никогда не сохраняйте папку node_modules.
    • Диапазон с указателем позволяет выполнять небольшие обновления и исправления, причем команда npm update работает внутри этого диапазона.
    • Для автоматизированных установок используйте команду npm ci.
    • Добавляйте зависимости осознанно; каждая из них — это код, которому вы доверяете.

    Так что в следующий раз, когда вы будете писать:

    npm install
    

    помните, что вы подключаете свой проект к экосистеме, созданной разработчиками со всего мира.

    Связанная литература