name, version
No need to say more.
exports
exports
define the public API for your library.
- Defines what can and cannot be imported from your library, and what the name of it is. If it’s not listed in
exports
, then developers cannotimport
/require
it. In other words, it acts like a public API for users of your library and helps define what is public and what is internal - Allows you to change which file is imported based on conditions (that you can define), such as “Was the file
import
ed orrequire
d?
One example that covers the most common use-cases:
{
"exports": {
".": {
"module": "./dist/index.mjs",
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"default": "./dist/index.mjs"
},
"./package.json": "./package.json"
},
"types": "./dist/index.d.ts"
}
"."
indicates the default entry for your package- The resolution happens from top to bottom and stops as soon as a matching field is found; the order of entries is very important
- The
module
field is an “unofficial” field that is supported by bundlers like Webpack and Rollup. It should come beforeimport
andrequire
, and point to anesm
-only bundle — which can be the same as your originalesm
bundle if it’s purelyesm
. As noted in the formats section, it is meant to help bundlers only include one copy of your library, no matter if it wasimport
ed orrequire
ed. For a deeper dive and the reasoning behind this decision, you can read more here, here, and here - The
import
field is for when someoneimport
s your library - The
require
field is for when someonerequire
s your library - The
default
field is used as a fallback for if none of the conditions match
If a bundler or environment understands the exports
field, then the package.json
’s top-level main, types, module, and browser fields are ignored, as exports
supersedes those fields.
main
defines the CommonJS entrymodule
defines the ESM entrytypes
defines the TypeScript types
files
The files
field indicates to the npm
CLI which files and folders to include when you package your library to be put on NPM’s package registry.
For example, if you transform your code from TypeScript into JavaScript, you probably don’t want to include the TypeScript source code in your NPM package. (Instead, you should include sourcemaps)
sideEffects
sideEffects
can either be set to false
to indicate that none of your modules have side effects, or an array of strings to list which files have side effects.
Much a like creating a pure function can bring benefits, creating a “pure module” enables certain benefits as well; bundlers can do a much better job of tree shaking your library.
peerDependencies
If you rely on another framework or library, set it as a peer dependency.
Example
{
"sideEffects": false,
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": ["./dist/*", "./dist/index.d.ts"]
}
},
"files": ["dist"]
}