> Что настраивается в файле package.json (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: ВСК

Стек: JavaScript

> Пример ответа

Короткий ответ

package.json - это центральный манифест Node.js-проекта. В нём описываются метаданные (имя, версия, лицензия), точка входа, scripts для автоматизации задач, зависимости (dependencies, devDependencies, peerDependencies, optionalDependencies), ограничения версий Node.js и npm, а также конфигурации инструментов (eslint, prettier, jest, babel и т.д.). Файл управляет воспроизводимостью окружения и является основой для npm, yarn и pnpm.

Подробное объяснение

package.json выполняет несколько ключевых функций:

Метаданные проекта: name, version, description, author, license, keywords, repository - используются для публикации в npm registry и идентификации пакета.

Точка входа: поле main (для CommonJS) и exports (современный стандарт, поддерживает conditional exports для ESM/CJS). module - неофициальное поле для bundler'ов (webpack, rollup), указывающее на ESM-версию.

Scripts: команды, запускаемые через npm run <script>. Это основной способ автоматизации: сборка, тесты, линтинг, деплой. Scripts имеют доступ к node_modules/.bin, поэтому можно вызывать утилиты без полного пути.

Зависимости:

  • dependencies - рантайм-зависимости, нужны в production
  • devDependencies - только для разработки (тесты, сборка, линтеры)
  • peerDependencies - плагины/библиотеки, требующие определённую версию хоста (например, react для react-dom)
  • optionalDependencies - необязательные, при ошибке установки npm продолжит работу
  • bundledDependencies - пакеты, включаемые в tarball при публикации

Версии Node.js и менеджеров: engines - ограничения на версии node/npm, packageManager - фиксация конкретного менеджера (например, pnpm@8.15.0).

Конфигурации инструментов: поля type ("module" или "commonjs"), browserslist, jest, eslintConfig, prettier, babel - позволяют хранить настройки в одном файле, хотя для сложных конфигов лучше отдельные файлы.

Прочее: files - список файлов для публикации, sideEffects - подсказка для tree-shaking, workspaces - монорепозитории, overrides/resolutions - принудительные версии транзитивных зависимостей.

На практике

Для senior-позиции важно понимать не просто "что там лежит", а trade-off'ы:

  • lock-файлы: package.json задаёт диапазоны версий (^, ~), а package-lock.json фиксирует точные версии. Для воспроизводимости сборки lock-файл обязателен в VCS.
  • type: "module": переключает интерпретацию .js файлов на ESM. Это влияет на __dirname, импорты JSON (нужен with { type: 'json' }), и на совместимость с CommonJS-пакетами.
  • exports vs main: exports - более строгий и современный, позволяет запретить доступ к внутренним файлам пакета ("./package.json" - исключение). Если поле exports есть, main игнорируется.
  • peerDependencies: частая ошибка - положить плагин в dependencies. Правильно - в peerDependencies + devDependencies для локальной разработки.
  • overrides: мощный, но опасный инструмент. Используется для форсирования версий транзитивных зависимостей при CVE или несовместимости, но может сломать чужой код.
  • workspaces: для монорепо. Важно понимать, как hoisting влияет на разрешение зависимостей.

Пример кода

JSON
{
"name": "my-app",
"version": "1.0.0",
"description": "Example package.json",
"type": "module",
"main": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./package.json": "./package.json"
},
"files": ["dist", "README.md"],
"sideEffects": false,
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
},
"packageManager": "pnpm@8.15.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"test": "vitest run",
"lint": "eslint . --ext .ts,.tsx",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"typescript": "^5.3.0",
"vite": "^5.0.0",
"vitest": "^1.0.0",
"eslint": "^8.56.0"
},
"peerDependencies": {
"react": ">=17.0.0"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.9.0"
},
"overrides": {
"lodash": "4.17.21"
},
"browserslist": [">0.2%", "not dead", "not op_mini all"]
}

Как отвечать на собеседовании

Начните с краткого определения, затем структурируйте ответ по блокам: метаданные, scripts, зависимости, ограничения окружения, конфигурации. Для senior-уровня обязательно добавьте:

  • объяснение разницы между dependencies и devDependencies с примерами
  • упоминание lock-файла и его роли в воспроизводимости
  • знание exports и conditional exports
  • понимание peerDependencies на примере плагинов
  • упоминание overrides и workspaces как продвинутых возможностей

Если спросят про конкретное поле - приведите пример из реального проекта. Покажите, что понимаете, как package.json связан с процессом сборки, CI и публикацией пакетов.

Что проверяет интервьюер

  • Глубина понимания: не просто перечисление полей, а понимание назначения и trade-off'ов
  • Практический опыт: знание реальных проблем (например, конфликт версий, hoisting, ESM/CJS)
  • Актуальность: знание современных практик (exports, packageManager, overrides)
  • Умение объяснять: способность структурировать ответ и приводить примеры
  • Внимание к деталям: понимание разницы между ^ и ~, dependencies и devDependencies

Типичные ошибки

  • Путаница между dependencies и devDependencies (например, класть typescript в dependencies)
  • Незнание разницы между main и exports
  • Утверждение, что package.json "хранит настройки" без конкретики
  • Игнорирование lock-файла - senior обязан упомянуть его роль
  • Непонимание peerDependencies - часто путают с devDependencies
  • Забывают про engines и packageManager для контроля окружения
  • Не упоминают sideEffects и его влияние на tree-shaking
  • Предлагают хранить сложные конфиги в package.json там, где нужен отдельный файл (например, eslint.config.js для flat config)

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью