ZL
About Articles Contact
Published on Apr 16, 2024
Filed under:
#node,
#npm

Understanding and using npm exports

npm exports lets you specify how users can import or require your files. (For instructions on using require, see below).

The basic syntax looks like this:

package.json
"name": "my-splendid-lib",
"exports": {
".": "./dist/main.js",
"./components": "./dist/components.js",
"./components/*": "./dist/components/*.js"
}

Let me explain what’s happening.

First, . is the path you use for people to import your library directly. If they import my-splendid-lib, they are actually importing the ./dist/main.js file.

/node_modules/my-splendid-lib/dist/main.js
import lib from 'my-splendid-lib'

./components (or any other name) lets people import with my-splendid-lib/components. By specifying ./components, you can determine what maps to. In this case, we mapped it to ./dist/components.js

/node_modules/my-splendid-lib/dist/components.js
import Components from `my-splendid-lib/components`

Finally, you use a * wildcard if you want to let users specify the paths themselves. This wildcard is often called a glob in the web development world.

In this case, if they imported my-splendid-lib/components/Accordion, Accordion will match the * wildcard. The actual file that will be imported will be ./dist/components/Accordion.js

/node_modules/my-splendid-lib/dist/components/Accordion.js
import Accordion from 'my-splendid-lib/components/Accordion'

That’s pretty much all you have to know if you only use ESM!

Differentiating Between CJS and ESM

For posterity:

  • CJS means Common JS
  • ESM means EcmaScript Modules

If you use Common JS, you need to require files. On the other hand, if you use ESM, you import files. There’s not much of a need to support CJS today because most people use the ESM import syntax.

// CJS
const lib = require('lib')
import lib from `lib`

If you’re writing a library that provides both CJS and ESM imports, then adding a require or import key to your exports map would do the trick.

"name": "my-splendid-lib",
"exports": {
".": {
"require": './dist/index.cjs',
"import": "./dist/index.mjs"
}
}

Now when a CJS loader requires your library, it will look under the require key and retrieve the ./dist/index.cjs file.

On the other hand, when an ESM loader imports your library, it will look for the import key and retrieve ./dist/index.mjs.

That’s it.

Not too hard, yeah? 😉

Now go and write your libraries and rock the world with your creations.

Previous Stress for Metamorphosis Next You can’t write like Seth Godin

Join My Newsletter

I share what I’m learning on this newsletter: code, building businesses, and living well.

Sometimes I write about technical deep-dives, product updates, musings on how to live, and sometimes my struggles and how I’m breaking through.

Regardless of the type of content, I do my best to send you an update every week.

If you’re into making things and growing as a person, you’ll probably feel at home here.

“

Zell is one of those rare people who commands tremendous knowledge and experience but remains humble and helpful. They want you to know what they know, not just be impressed by it.

In other words, Zell is a natural teacher. You’re lucky to have him because he feels lucky to be able to help you in your journey.

Heydon Pickering
Heydon Pickering — Web & Accessibility Extraordinaire
The Footer

General

Home About Contact Testimonials Tools I Use

Projects

Magical Dev School Splendid Labz

Socials

Youtube Instagram Tiktok Github Bluesky X

Follow Along

Email RSS
© 2013 - 2025 Zell Liew / All rights reserved / Terms