Dan Levy's Avatar DanLevy.net

ESM exports: named vs. default?

To name, or not to name?

ESM exports: named vs. default?

Should you use named or default exports in JavaScript?

There’s no shortage of strongly worded articles on this topic.

The majority judge default export as “terrible.” Others maintain default should win (e.g. AirBnb style guide.)

They often blame entirely temporary things: IDE auto-import bugs, a particular bundler’s tree-shaking abilities, or the mere possibility of typos when naming an import.

Have we missed the point of exporting in the first place?

Code is Communication. ✨

We are sending a signal to importers how to use a thing.

So, what are we saying?

Broadly speaking, there are 2 ways to export things in modern JavaScript:

Of course you can combine both, or use different approaches for different parts of your codebase. See more examples at the end of the article.

Weak Args, Man

Let’s address some of the common “temporary issues” folks run into.

// You can alias using both!
import { Knife as Handle } from "./knife.js"; // 🔪
import { default as Handle } from "./knife.js"; // 🔪
import Handle from "./knife.js"; // 🔪

Summary

There are actually many combinations of ways we could export things, each tells a different story:

Default (Exports)Named (Exports)Private FnsPatternMeaning
One default export.“Presenting ONE function w/ Single Purpose!”
One named export.“Please don’t rename me.”
Default export + multiple ‘private’ un-exported functions“Here’s some related logic. Also, expect class-ish behavior.“
Multiple named exports, generic file name.“A grab-bag of loosely related things, no hierarchy implied.”
Single named export ALSO exported as default.“You can’t mess up importing me.”

Something to think about: What are we saying when the file name does or doesn’t match one of its exports? (For example, a utils.js with many functions.)

Conclusion

If Code is Communication, please export like you fucking mean it. 💞

Edit on GitHubGitHub