Gyaan

Modules

beginner modules import export ES6 CommonJS

Before modules, all JavaScript code shared one global scope — which was a nightmare for large projects. Modules let us split code into separate files, each with its own scope, and explicitly share only what we want.

Named Exports and Imports

We can export multiple things from a file by name. When importing, we use the exact same names (inside curly braces).

// math.js
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export function multiply(a, b) { return a * b; }

// app.js
import { PI, add, multiply } from './math.js';
console.log(add(2, 3)); // 5

We can also rename imports if there’s a name collision:

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

Default Exports and Imports

Each file can have one default export. When importing a default, we don’t use curly braces and we can name it anything we want.

// logger.js
export default function log(msg) {
  console.log(`[LOG] ${msg}`);
}

// app.js — we can call it whatever we want
import log from './logger.js';
import myLogger from './logger.js'; // this works too

We can mix default and named exports in the same file, though it’s generally cleaner to pick one style.

// utils.js
export default function main() { /* ... */ }
export const VERSION = '1.0';

// app.js
import main, { VERSION } from './utils.js';

Re-exporting

When building a library or module with multiple files, we can re-export from an index file to create a clean public API.

// components/index.js
export { Button } from './Button.js';
export { Modal } from './Modal.js';
export { default as Card } from './Card.js';

// app.js — clean single import
import { Button, Modal, Card } from './components/index.js';

Dynamic Imports

Sometimes we don’t want to load a module until we actually need it. import() returns a Promise, so we can use it with await or .then().

// Load a heavy module only when the user clicks
button.addEventListener('click', async () => {
  const { Chart } = await import('./chart.js');
  const chart = new Chart('#canvas');
  chart.render(data);
});

This is great for code splitting — the browser doesn’t download the module until it’s needed, making the initial page load faster.

CommonJS vs ES Modules

This is a common interview question. CommonJS (require) is the old Node.js way. ES Modules (import/export) is the standard that works in both browsers and modern Node.js.

// CommonJS (Node.js traditional way)
const fs = require('fs');
module.exports = { myFunction };
module.exports = myFunction; // default-like export

// ES Modules (modern standard)
import fs from 'fs';
export { myFunction };
export default myFunction;

Key differences:

  • CommonJS loads modules synchronously at runtime. require can be called anywhere, even inside if blocks.
  • ES Modules are statically analyzed at build time. import must be at the top level (except dynamic import()).
  • CommonJS uses require() / module.exports. ES Modules use import / export.
  • In Node.js, use .mjs extension or set "type": "module" in package.json to use ES Modules.

In simple language, if we’re writing modern JavaScript (whether for the browser or Node.js), we should use ES Modules. CommonJS still works in Node.js but ES Modules are the future.