Skip to main content
Practice Problems

JavaScript modules: import/export, CommonJS vs es modules

What are JavaScript Modules?

Modules allow you to split code into separate files, each with its own scope. They help organize code, prevent naming conflicts, and enable reusability.


ES Modules (ESM)

The modern standard, supported in browsers and Node.js.

Named Exports

javascript
// math.js export const PI = 3.14159; export function add(a, b) { return a + b; } export function multiply(a, b) { return a * b; } // main.js import { PI, add, multiply } from './math.js'; import { add as sum } from './math.js'; // rename import * as math from './math.js'; // namespace import

Default Export

javascript
// User.js export default class User { constructor(name) { this.name = name; } } // main.js import User from './User.js'; // any name works import MyUser from './User.js'; // same thing

Mixed Exports

javascript
// api.js export const BASE_URL = "/api"; export default function fetchData(endpoint) { return fetch(BASE_URL + endpoint); } // main.js import fetchData, { BASE_URL } from './api.js';

Re-exporting

javascript
// index.js (barrel file) export { default as User } from './User.js'; export { default as Product } from './Product.js'; export * from './utils.js';

CommonJS (CJS)

The Node.js module system (before ES modules):

javascript
// math.js const PI = 3.14159; function add(a, b) { return a + b; } module.exports = { PI, add }; // or: exports.PI = PI; // main.js const { PI, add } = require('./math'); const math = require('./math');

ESM vs CommonJS Comparison

FeatureES ModulesCommonJS
Syntaximport/exportrequire()/module.exports
LoadingStatic (compile-time)Dynamic (runtime)
Top-level awaitYesNo
Tree shakingYesNo
Browser supportYes (native)No (needs bundler)
Node.js.mjs or "type": "module"Default in Node.js
HoistingImports are hoistedNot hoisted

Dynamic Imports

javascript
// Load module on demand (code splitting) const module = await import('./heavyModule.js'); module.doSomething(); // Conditional loading if (condition) { const { feature } = await import('./feature.js'); feature(); } // React lazy loading const LazyComponent = React.lazy(() => import('./Component'));

Module Scope

Each module has its own scope — variables declared in a module are not global:

javascript
// counter.js let count = 0; export const increment = () => ++count; export const getCount = () => count; // main.js import { increment, getCount } from './counter.js'; increment(); // count is 1, but only inside counter.js

Important:

Use ES Modules for all modern projects. They enable tree shaking (removing unused code), static analysis, and are the standard. Use dynamic import() for code splitting and lazy loading.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems