Skip to content

Using Modules

Difference between export default and export

The difference between export default and export in JavaScript (ES6 modules) lies in how they are used to export and import values from a module.

1. export default

  • Used to export a single value from a module.
  • Can be a function, class, or object.
  • When importing, you can name it whatever you want.

Example:

Exporting (file: math.js)

javascript
export default function add(a, b) {
  return a + b;
}

Importing (file: app.js)

javascript
import sum from './math.js'; // Name can be anything
console.log(sum(2, 3)); // Output: 5

2. export (Named Export)

  • Used to export multiple values from a module.
  • Must be imported using the exact same name (or using as to rename).

Example:

Exporting (file: math.js)

javascript
export function add(a, b) {
  return a + b;
}

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

Importing (file: app.js)

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

Renaming with as:

javascript
import { add as sum } from './math.js';
console.log(sum(2, 3)); // Output: 5

Key Differences:

Featureexport defaultexport (Named Export)
Number of ExportsOnly one per moduleMultiple per module
Import SyntaxCan use any nameMust match the exported name
Use CaseDefault value of a module (e.g., a class, function)Utility functions, constants, multiple exports

Can You Use Both Together?

Yes, a module can have both a default export and named exports.

Example:

javascript
export default function multiply(a, b) {
  return a * b;
}

export const PI = 3.14;
export function divide(a, b) {
  return a / b;
}

Importing:

javascript
import multiply, { PI, divide } from './math.js';

console.log(multiply(2, 3)); // Output: 6
console.log(PI); // Output: 3.14
console.log(divide(6, 2)); // Output: 3

Difference between module.exports and exorts.foo

Great question! Now you're diving into the difference between ES Modules (ESM) and CommonJS (CJS), which is crucial when working in both Node.js and modern front-end JavaScript.


CommonJS (module.exports vs. exports.foo)

CommonJS is the module system used in Node.js (before ES Modules were introduced). The key difference is in how exports are handled.

1️⃣ module.exports

  • Exports a single value (object, function, class, etc.).
  • If you assign module.exports to something, it overwrites exports.
Example: math.js
javascript
// Exporting a single function
module.exports = function add(a, b) {
  return a + b;
};
Importing: app.js
javascript
const add = require('./math'); // No curly braces needed
console.log(add(2, 3)); // Output: 5

2️⃣ exports.foo (Shorthand for module.exports)

  • Exports multiple values as an object.
  • exports is just a reference to module.exports, so modifying exports.foo works.
  • BUT: Assigning exports directly will break the reference.
Example: math.js
javascript
exports.add = function (a, b) {
  return a + b;
};

exports.subtract = function (a, b) {
  return a - b;
};
Importing: app.js
javascript
const math = require('./math');
console.log(math.add(5, 3)); // Output: 8
console.log(math.subtract(5, 3)); // Output: 2

🚨 Common Mistake: Overwriting exports

If you assign exports directly, it breaks the connection with module.exports.

javascript
exports = function add(a, b) {  // ❌ WRONG
  return a + b;
};

💡 Fix: Always use module.exports if exporting a single function or object.

javascript
module.exports = function add(a, b) { // ✅ Correct
  return a + b;
};

ES Modules (export default vs. export) vs. CommonJS

Featureexport default / export (ESM)module.exports / exports.foo (CJS)
Module SystemES Modules (ESM)CommonJS (CJS)
Export TypeNamed and Default ExportsSingle or Multiple Exports
Import Syntaximport ... from 'file'require('file')
UsageFrontend (and Node.js with ESM)Node.js (by default)
Default Exportexport default (one per file)module.exports = value
Multiple Exportsexport { foo, bar }exports.foo = value; exports.bar = value

When to Use What?

  • Use export / export default when working in modern JavaScript (browser-based or ES Module-enabled Node.js).
  • Use module.exports / exports.foo when working with CommonJS (default in Node.js).
  • If using Node.js with ES Modules ("type": "module" in package.json), use import/export instead of require.

Inspecting Exports

If a package doesn’t provide sufficient documentation on how it exports modules, you can determine whether it provides default exports, named exports, or a separate entry point using the following methods:


1️⃣ Use console.log() to Inspect the Module

If the documentation isn’t clear, you can simply log the imported module to check its structure.

Try Importing and Logging It

For ES Modules
javascript
import * as myModule from 'some-module';
console.log(myModule);

This will print all exported properties, helping you see whether it has named exports or if the entire module is a default export.

For CommonJS Modules
javascript
const myModule = require('some-module');
console.log(myModule);

How to Interpret the Output

  • If you see an object with multiple functions/properties:

    javascript
    {
      foo: [Function],
      bar: [Function]
    }

    → Use named imports:

    javascript
    import { foo, bar } from 'some-module';
  • If you see a function or class directly:

    javascript
    [Function: someModule]

    → It’s a default export:

    javascript
    import someModule from 'some-module';
  • If it's wrapped inside .default like this:

    javascript
    {
      default: [Function: someModule]
    }

    → The module is using CommonJS with a default export, and you should do:

    javascript
    import someModule from 'some-module';

2️⃣ Use Object.keys() to List Exports

javascript
import * as myModule from 'some-module';
console.log(Object.keys(myModule));
  • If you see multiple keys → Named exports are available.
  • If you see only ["default"] → It's a default export.

3️⃣ Check package.json for ESM Entry Points

Look at the module’s package.json inside node_modules/some-module/package.json. Check for the following fields:

  • main → CommonJS entry point
  • module → ESM entry point
  • exports → Might define multiple entry points

Example:

json
{
  "main": "dist/index.cjs",
  "module": "dist/index.esm.js",
  "exports": {
    "import": "./dist/index.esm.js",
    "require": "./dist/index.cjs"
  }
}
  • If "module" or "import" exists, use import.
  • If only "main" exists, it's likely CommonJS.

4️⃣ Use require.resolve() to Find the Entry File

javascript
console.log(require.resolve('some-module'));

This will print the exact file being imported, helping you check the module type.


5️⃣ Read the Actual Source Code

If all else fails, go to:

  • node_modules/some-module/dist/index.js (or similar)
  • Open the file and check how it exports values:
    • Default export (ESM):
      javascript
      export default function someModule() { ... }
    • Named exports (ESM):
      javascript
      export function foo() { ... }
      export function bar() { ... }
    • CommonJS export:
      javascript
      module.exports = function someModule() { ... };
    • CommonJS named exports:
      javascript
      module.exports = { foo, bar };

6️⃣ Test Different Import Styles

If you're still unsure, try different import styles one by one:

javascript
import someModule from 'some-module'; // Try default import
import { foo } from 'some-module'; // Try named import
import * as someModule from 'some-module'; // Try namespace import

If you get an error like:

TypeError: someModule is not a function

Then it's likely not a default export. Adjust accordingly.


🛠 TL;DR – Steps to Determine Module Export Type

  1. Log the imported module (console.log(myModule)) ✅
  2. Use Object.keys() to list exports ✅
  3. Check package.json for "module" and "exports"
  4. Use require.resolve() to find the entry file ✅
  5. Open the source file in node_modules/ and inspect the exports ✅
  6. Test different import styles

Importing Styles

When using import someModule from 'some-module', you can use whatever name you want as long as you're importing a default export.


1️⃣ Default Export: Any Name Works

If a module exports a default value:

javascript
export default function myFunction() {
  console.log("Hello World");
}

You can import it using any name:

javascript
import anything from 'some-module';

anything(); // Output: "Hello World"

The name does not have to match the original exported name.


2️⃣ Named Exports: Must Use Exact Name

If a module uses named exports:

javascript
export function myFunction() {
  console.log("Hello World");
}
export function anotherFunction() {
  console.log("Another function");
}

You must import using the exact exported names:

javascript
import { myFunction, anotherFunction } from 'some-module';

myFunction(); // ✅ Works
anotherFunction(); // ✅ Works

Wrong Example:

javascript
import { notMyFunction } from 'some-module'; // ❌ Error: notMyFunction is not defined

3️⃣ Renaming Named Exports with as

If you want to rename a named export, use as:

javascript
import { myFunction as customName } from 'some-module';

customName(); // ✅ Works

4️⃣ Import Everything as an Object (import * as syntax)

You can import all named exports under a namespace:

javascript
import * as someModule from 'some-module';

someModule.myFunction(); // ✅ Works
someModule.anotherFunction(); // ✅ Works

🚀 Summary

Export TypeImport StyleCan Rename?
Default Export (export default)import anyName from 'some-module';✅ Yes, any name
Named Export (export function foo())import { foo } from 'some-module';❌ No, must match
Named Export (renamed)import { foo as bar } from 'some-module';✅ Yes, using as
Namespace Import (import * as)import * as someModule from 'some-module';✅ Yes, but must use someModule.foo()

Credit @Wayne19980