#Что означает ошибка и когда она возникает
При npm ci --omit=dev npm не распаковывает devDependencies на диск. Если код, запускаемый на сервере, требует такой пакет, появляется MODULE_NOT_FOUND или ERR_MODULE_NOT_FOUND, хотя на компьютере разработчика приложение работает. Не путайте это с dev-зависимостями, нужными только на этапе сборки.
#Как отличить возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Пакет ошибочно записан в devDependenciesРабочий код использует runtime-библиотеку, например dotenv, а она отмечена как зависимость только разработки. | В package.json имя находится под devDependencies, но отсутствует в dependencies. | Перенести пакет в зависимости исполнения. |
| Запускается исходник вместо собранного приложенияНа сервер отправили исходники TypeScript или другой код, который требует сборщик из devDependencies. | После omit=dev нет tsc/webpack, сборка не проводилась либо отсутствует dist. | Собирать в отдельной среде с dev-зависимостями, запускать готовый результат. |
Скрипт запуска вызывает средство разработкиВ scripts.start записано nodemon или ts-node, исключённое из производственной установки. | npm start падает с command not found, хотя сам Node установлен. | Заменить производственный запуск на node готового файла. |
#Пошаговая диагностика и устранение
- Сравните локальный и серверный способ запускаОткройте package.json в редакторе VS Code и найдите scripts.start, scripts.build и imports из файла, который падает. Запишите, как устанавливаются зависимости на сервере:
npm ci --omit=dev,npm install --productionили NODE_ENV=production. Не изменяйте сервер до выяснения отсутствующего имени пакета. - Сохраните сообщения об ошибке и версииВ терминале проекта выполните
node --versionиnpm --version; запустите исходную команду приложения и сохраните точное имя модуля из MODULE_NOT_FOUND. В Node.js пакет может быть вложенной зависимостью, поэтому отсутствие имени в вашем package.json само по себе не доказывает проблему omit=dev. - Проверьте раздел, где указан пакетОткройте package.json и посмотрите, находится ли отсутствующий модуль в
devDependenciesилиdependencies. Для конкретного примера dotenv выполнитеnpm pkg get dependencies.dotenv devDependencies.dotenvиз корня проекта; результат показывает версии либо{}/отсутствие свойства. Если приложение требует пакет только при разработке, переносить его в production не нужно. - Отделите зависимости исполнения от сборкиНайдите импорт отсутствующего пакета: если он в файлах, реально исполняемых командой node на сервере, это зависимость исполнения. Если пакет нужен лишь при
npm run build, в выпуске допустимо не иметь его, но сборку нужно завершить заранее. Сохраняйте готовый dist и не переносите вместе с ним лишние инструменты при отсутствии потребности. - Перенесите runtime-пакет в dependenciesВ отдельной ветке проекта для подтверждённой runtime-библиотеки выполните
npm install dotenv --save-prod, если именно dotenv импортируется рабочим кодом. Для другого пакета используйте его реальное имя и согласованную версию. Команда меняет package.json, package-lock.json и node_modules; просмотрите изменения перед включением в выпуск. - Проверьте сценарий установки без dev-зависимостейСначала сделайте отдельную копию проекта без пользовательских данных и скриптов отладки. В копии, где есть сохранённый lock-файл, выполните
npm ci --omit=dev; учтите: npm ci удалит существующий node_modules этой копии. Затем выполните обычную команду запуска продукта — она должна находить runtime-библиотеки. - Если пакет нужен только для сборки, исправьте порядок этаповВ процессе сборки выполняйте npm ci со всеми нужными зависимостями, затем npm run build; для запуска используйте подготовленные артефакты и зависимости исполнения. В Docker можно применять раздельные стадии, но не копируйте секреты и лишние исходники в итоговый образ. Если команда scripts.start ссылается на nodemon, измените её на предусмотренный продуктом запуск Node после тестирования.
- Убедитесь, что локальная и производственная среды совпалиВ копии сделайте
npm ls dotenv --omit=devдля примера с dotenv, запустите приложение и выполните его реальное действие. Не публикуйте.envи значения секретов в журнале. Если произошёл новый MODULE_NOT_FOUND, найдите следующую неверно классифицированную зависимость; для отката верните package.json и lock-файл из Git и пересоберите копию. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Минимальный пример и проверка на тестовом проекте
{
"scripts": {"start": "node dist/server.js"},
"dependencies": {"dotenv": "^16.0.0"},
"devDependencies": {"typescript": "^5.0.0"}
}#Проверка результата и действия при неуспехе
После установки с omit=dev рабочий запуск проходит без MODULE_NOT_FOUND; сборка выполняется на отдельном шаге и не зависит от инструментов, отсутствующих в выпуске. Если проблема сохраняется, укажите точное отсутствующее имя, файлы imports и порядок стадий сборки.