package.json exports: advanced
Поле exports — мощный механизм инкапсуляции публичного API пакета с поддержкой условных экспортов, subpath patterns и блокировкой internal paths; знание нюансов обязательно при публикации npm-пакетов.
// Полная структура exports для dual ESM/CJS пакета// package.json:// {// "name": "my-lib",// "version": "1.0.0",// "type": "module",// "main": "./dist/index.cjs", // legacy для старых инструментов// "exports": {// ".": {// "types": "./dist/index.d.ts", // TypeScript — ПЕРВЫМ!// "import": "./dist/index.mjs", // ESM// "require": "./dist/index.cjs", // CJS// "default": "./dist/index.mjs" // fallback// },// "./utils": {// "types": "./dist/utils.d.ts",// "import": "./dist/utils.mjs",// "require": "./dist/utils.cjs"// },// "./package.json": "./package.json" // разрешаем чтение package.json// }// }// Subpath patterns: glob * (Node.js 16+)// "exports": {// "./features/*": {// "import": "./dist/features/*.mjs",// "require": "./dist/features/*.cjs",// "types": "./dist/features/*.d.ts"// }// }// import { auth } from 'my-lib/features/auth'// → ./dist/features/auth.mjs
// Блокировка internal paths: главное преимущество exports// Без записи в exports → ERR_PACKAGE_PATH_NOT_EXPORTED// import 'my-lib/src/internal-helper' // ← ошибка даже если файл есть
// "imports" field: self-references ВНУТРИ пакета// "imports": {// "#utils": "./src/utils.mjs",// "#config": {// "node": "./src/config.node.mjs",// "default": "./src/config.browser.mjs"// }// }// import { fn } from '#utils'; // работает только внутри пакета// Кастомные условия и порядок (ВАЖЕН!)// "exports": {// ".": {// "types": "./dist/index.d.ts", // TypeScript ПЕРВЫМ// "development": "./dist/dev.mjs", // --conditions=development// "production": "./dist/prod.mjs",// "import": "./dist/index.mjs",// "require": "./dist/index.cjs",// "default": "./dist/index.mjs" // ПОСЛЕДНИМ// }// }
// webpack.config.js — подключить кастомные условия:// resolve: { conditionNames: ['development', 'import', 'module', 'default'] }
// Node.js CLI:// node --conditions=development app.js
// Типичные ошибки:// 1. "types" не первым → tsc берёт неверный .d.ts (по условию "import")// 2. Нет "default" → некоторые инструменты падают// 3. "module" вместо "exports"."import" → bundler OK, Node.js игнорируетИтог: exports — единственный правильный способ публиковать dual CJS/ESM пакет с TypeScript types; subpath exports блокируют доступ к internal путям и формируют стабильный публичный API.