Default Exports vs Named Exports in ESM and CJS: A Deep Dive for JavaScript Developers

Aditya Yadav
4 min readDec 16, 2024

--

In JavaScript, modules allow developers to organize code into reusable, independent pieces. Two primary ways to export and import these modules are default exports and named exports, each with unique syntax, use cases, and benefits. Let’s explore their differences and how to leverage them effectively in your projects.

Default Exports: Simplicity at Its Best

What Are Default Exports?

Default exports allow you to export a single value, function, or class as the primary output of a module. They’re great for cases where a module represents a single responsibility or utility.

Syntax

// file: math.js
export default function add(a, b) {
return a + b;
}

Importing Default Exports

With default exports, you can import using any name of your choice. This flexibility is perfect for keeping code intuitive and context-aware.

// file: app.js
import sum from './math.js';
console.log(sum(3, 5)); // Output: 8

Why Choose Default Exports?

  • Flexibility: Importers can rename the export as needed.
  • Best for Single Responsibility: Ideal when your module offers one core feature or function.

Key Limitations

  • A module can only have one default export.
  • Lack of clarity in large projects, as the default export’s purpose isn’t always obvious.

Named Exports: Clarity for Multiple Utilities

What Are Named Exports?

Named exports allow you to export multiple values, functions, or objects from a single module, each identified by a unique name.

Syntax

// file: math.js
export function add(a, b) {
return a + b;
}

export function subtract(a, b) {
return a - b;
}

Importing Named Exports

With named exports, you must use the exact exported names in curly braces. This encourages explicitness and reduces ambiguity.

// file: app.js
import { add, subtract } from './math.js';
console.log(add(5, 3)); // Output: 8
console.log(subtract(5, 3)); // Output: 2

You can also import everything at once and reference each export through an object:

import * as math from './math.js';
console.log(math.add(5, 3)); // Output: 8
console.log(math.subtract(5, 3)); // Output: 2

Why Choose Named Exports?

  • Explicit and Descriptive: Perfect for modules with multiple utilities or values.
  • Scalable: Encourages modular and reusable design.

Key Limitations

  • Requires precise import names, which can be verbose in some cases.
  • Can feel less flexible when compared to default exports.

Default vs Named Export in CommonJS (CJS)

1. Default Export in CJS

In CommonJS, there is no explicit syntax for default exports like in ES Modules (ESM). However, you can simulate default exports by assigning the exported value directly to module.exports. This way, when the module is imported, the entire object or function can be directly accessed.

Example: Default Export in CJS

// math.js (CJS)
module.exports = function add(a, b) {
return a + b;
};

// main.js (CJS)
const add = require('./math');
console.log(add(2, 3)); // Output: 5

How It Works: The module.exports object holds the entire exported value. In this case, it’s a function, which is then imported using require() and used directly.

2. Named Export in CJS

Named exports in CommonJS are implemented by adding properties to the exports object. This allows multiple entities (functions, objects, etc.) to be exported from a module.

Example: Named Export in CJS

// math.js (CJS)
exports.add = function (a, b) {
return a + b;
};
exports.subtract = function (a, b) {
return a - b;
};

// main.js (CJS)
const math = require('./math');
console.log(math.add(2, 3)); // Output: 5
console.log(math.subtract(5, 3)); // Output: 2
  • How It Works: Each function is assigned to exports as a named property. In the importing file, you can access these properties through the require() function.

Key Differences: Default vs Named Exports

Mixing Default and Named Exports

While you can mix default and named exports in a single module, it’s essential to keep things organized.

// file: utilities.js
export default function greet(name) {
return `Hello, ${name}!`;
}

export const pi = 3.14159;
export const square = (x) => x * x;
// file: app.js
import greet, { pi, square } from './utilities.js';
console.log(greet('Alice')); // Output: Hello, Alice!
console.log(pi); // Output: 3.14159
console.log(square(4)); // Output: 16

What Happens During Import?

Default Export:

  • Automatically binds the default export to the variable you specify during import.
  • In CommonJS, the module.exports value is assigned directly.

Named Export:

  • Uses destructuring to pick specific exports.
  • import * bundles all named exports into an object, which can be used like a namespace.

Dynamic Imports:

  • Both types can be dynamically imported using the import() function in ES Modules:
(async () => {
const module = await import('./math.js');
console.log(module.add(3, 2)); // Named export
console.log(module.default(3, 2)); // Default export
})();

When to Use Default vs Named Exports?

Use Default Exports When:

  • A module offers a single, core feature or function.
  • Simplicity and flexibility in importing matter most.

Use Named Exports When:

  • A module provides multiple utilities or values.
  • Explicit imports improve clarity and maintainability.

Conclusion: Choosing the Right Export

The choice between default and named exports depends on your project needs. Default exports offer simplicity and flexibility, ideal for single-use modules. Named exports, on the other hand, excel at providing clarity and scalability when working with modules that contain multiple utilities.

Pro Tip: For large-scale projects, strive for consistency in your export strategy. Mixing too many default and named exports across modules can lead to confusion. Pick one approach where it makes the most sense and stick with it!

What’s your take on default vs named exports? Share your thoughts or questions in the comments! Let’s spark a discussion and help each other master JavaScript module management.

--

--

Aditya Yadav
Aditya Yadav

Written by Aditya Yadav

Software Engineer who talks about tech concepts in web development

No responses yet