dependencies или devDependencies — в чём разница, и почему из-за неё падает деплой

Сначала неожиданное. Для обычного сайта на Vite или React почти неважно, в какой раздел package.json попал пакет. Сборщик возьмёт в итоговый код всё, что ты импортировал, — из любого раздела.
А теперь вторая половина. Эта же «неважная» разница роняет деплой с ошибкой sh: vite: not found. На ноутбуке всё собирается, на сервере — нет. Разберём, когда раздел решает всё, а когда — ничего.
Что это за два списка
В package.json зависимости лежат в двух списках:
- dependencies — то, что нужно программе, чтобы работать. React, клиент базы данных, библиотека для дат.
- devDependencies — то, что нужно разработчику, чтобы её собрать и проверить. Сборщик Vite, TypeScript, линтер, тесты,
@types/....
Аналогия: ты делаешь стул на заказ. Доски и шурупы — это dependencies, они станут частью стула. Пила и рубанок — devDependencies. Без них стул не сделать, но заказчику ты их не отправляешь.
Добавляются они разными командами:
npm install dayjs # в dependencies
npm install -D vitest # в devDependencies (-D = --save-dev)
pnpm add -D vitest # то же в pnpm
Сравнение по пунктам
- Ставится командой
npm installу тебя на компьютере: dependencies — да; devDependencies — да. Локально разницы нет вообще. - Ставится при
npm install, еслиNODE_ENV=production: dependencies — да; devDependencies — нет. npm пропускает их по умолчанию. - Ставится при
npm ci --omit=dev: dependencies — да; devDependencies — нет. Так собирают лёгкие Docker-образы. - Попадает в бандл сайта: решает не раздел, а импорт. Импортировал в коде — сборщик включит пакет, откуда бы он ни был.
- Ставится тем, кто установит твою библиотеку из npm: dependencies — да; devDependencies — никогда.
- Типичное содержимое: dependencies — React, Express, Supabase-клиент; devDependencies — Vite, TypeScript, ESLint, Vitest, Prettier.
Где эта разница бьёт больно
1. Сборка на сервере. Это та самая ошибка vite: not found. Частый сценарий — Dockerfile:
ENV NODE_ENV=production
RUN npm ci # devDependencies пропущены
RUN npm run build # ✗ vite: not found
Переменная NODE_ENV=production стоит выше установки, поэтому npm не поставил Vite. А собрать без него нельзя. Починка — ставить всё для сборки, а production включать уже после:
RUN npm ci
RUN npm run build
ENV NODE_ENV=production
Другие частые причины падения деплоя собраны в статье почему не работает деплой.
2. Сервер на Node. Если твой бэкенд на Express работает без сборки, в продакшне ставят только dependencies. Положил express в devDependencies — сервер не запустится: Cannot find module 'express'. Локально при этом всё работает, ведь дома ставится всё.
3. Своя библиотека. Если ты публикуешь пакет в npm, тот, кто его установит, получит только твои dependencies. Забыл туда нужный пакет — у тебя всё работает, а у пользователей всё падает.
А что за третий раздел — peerDependencies
Иногда в package.json чужой библиотеки встречается ещё один список — peerDependencies. Это просьба: «я плагин для React, но свой React не привезу — используй тот, что уже есть в проекте». Иначе в проекте оказались бы две копии React, и хуки бы сломались. В своём сайте этот раздел тебе почти никогда не понадобится. Но если npm ругается на peer dependency при установке — речь именно о нём: версия твоего React не та, что ждёт плагин.
Кому что подойдёт
Без увиливаний:
- Сайт или фронтенд на Vite / Next: клади в devDependencies всё, что нужно только для сборки и проверки. Остальное — в dependencies. Ошибёшься в мелочи — сайт не сломается. Главное — не ставь
NODE_ENV=productionдо установки. - Сервер на Node без сборки: будь строгим. Всё, что делает
requireилиimportво время работы, — только в dependencies. - Библиотека для npm: строже всего. Проверь установку в чистой папке, прежде чем публиковать.
Как перенести пакет из одного раздела в другой?
Установи его ещё раз с нужным флагом: npm install -D eslint перенесёт его в devDependencies, а npm install eslint — обратно. Или поправь package.json руками и запусти npm install.
А что делает lock-файл с devDependencies?
В package-lock.json записаны все пакеты из обоих разделов. Флаг --omit=dev не меняет файл — он только не ставит лишнее на диск. Про разные менеджеры пакетов — в сравнении npm, pnpm и yarn.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





