DevBolt
Processed in your browser. Your data never leaves your device.

package.json exports Field Guide

The exports field is how modern npm packages support both CommonJS and ESM consumers. Use the generator above with the 'exports field' option to see how it works.

Basic Info

Module Config

devnext dev
buildnext build
startnext start
lintnext lint
next^15.0.0
react^19.0.0
react-dom^19.0.0
typescript^5.7.0
@types/node^22.0.0
@types/react^19.0.0
@types/react-dom^19.0.0
eslint^9.0.0
eslint-config-next^15.0.0
package.json
{
  "name": "my-nextjs-app",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "main": "index.js",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "^15.0.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "typescript": "^5.7.0",
    "@types/node": "^22.0.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "eslint": "^9.0.0",
    "eslint-config-next": "^15.0.0"
  },
  "license": "MIT"
}

4

Scripts

3

Deps

6

DevDeps

Press Ctrl+Enter to copy

Why exports matters

The exports field replaces main/module/types as the primary entry point mechanism. It provides encapsulation (consumers can only import exported paths), conditional resolution (different code for import vs require), and subpath exports (import 'pkg/utils'). Node.js 12.7+ and all modern bundlers support it.

Conditional exports for dual packages

A dual CJS/ESM package uses conditional exports to serve different files. 'import' condition serves ESM (.mjs or .js with type:module), 'require' serves CJS (.cjs or .js with type:commonjs), and 'types' serves TypeScript declarations. Build tools like tsup generate both formats automatically.

Common patterns

Single entry: { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" } }. Subpath exports: { "./utils": { "import": "./dist/utils.mjs" } }. Wildcard: { "./*": "./dist/*.js" }. Always list 'types' first — TypeScript resolves top-to-bottom.

Migration from main/module

Keep main and module alongside exports for backwards compatibility with older Node.js versions and bundlers. exports takes priority when supported. Set types at the top level too for older TypeScript versions. Once you drop Node.js <12.7 support, exports alone is sufficient.

Frequently Asked Questions

Do I need both main and exports?

For maximum compatibility, yes. exports is used by Node.js 12.7+ and modern bundlers, while main is the fallback for older environments. If you only target modern Node.js (16+), exports alone is fine.

What order should conditions be in?

TypeScript types should come first, then import, then require, then default. Node.js resolves conditions top-to-bottom and uses the first match. Putting types first ensures TypeScript picks up declarations before runtime conditions.

Can I use exports to hide internal files?

Yes. Once you add an exports field, only the explicitly exported paths are accessible to consumers. Trying to import an unexported path throws ERR_PACKAGE_PATH_NOT_EXPORTED. This is a key advantage over main/module which exposes the entire package.

Related Generate Tools