JavaScript course menu
JavaScript Modules: import and export Explained
Learn JavaScript ES modules: named and default exports, importing with import, renaming, namespace imports, modules in the browser with type=module, modules in Node.js (.mjs and type: module), dynamic import(), module scope, and CommonJS require.
On this page
As programs grow, keeping everything in one file becomes unmanageable. Modules let you split code into files, each with its own scope, that explicitly export what others may use and import what they need.
Exporting and importing#
export const GST_RATE = 0.18;
export function withGst(price) {
return price + price * GST_RATE;
}
export function formatPrice(amount) {
return `₹${amount.toFixed(2)}`;
}
function internalHelper() {
// not exported: private to this file
}import { withGst, formatPrice } from "./math-utils.js";
console.log(formatPrice(withGst(500))); // ₹590.00exportbefore a declaration makes it available to other modules.import { a, b } from "./file.js"brings in exactly those names.- Anything not exported stays private to its file.
- The path starts with
./or../for your own files, and in browsers it must include the.jsextension.
Default exports#
A module can have one default export, typically its main class or function. It is imported without braces, under any name you choose:
export default class ShoppingCart {
items = [];
add(item) { this.items.push(item); }
}import ShoppingCart from "./ShoppingCart.js";
import Cart from "./ShoppingCart.js"; // any name works for a default export
const cart = new ShoppingCart();Many teams prefer named exports, because the names stay consistent across the codebase and editors can auto-import them reliably.
Renaming and namespace imports#
import { formatPrice as format } from "./math-utils.js"; // rename on import
import * as MathUtils from "./math-utils.js"; // everything, as one object
console.log(format(10));
console.log(MathUtils.GST_RATE);You can also export a list at the end of a file, and re-export from another module:
export { withGst, formatPrice as format };
export { default as ShoppingCart } from "./ShoppingCart.js";Modules in the browser#
Load the entry file with type="module":
<script type="module" src="main.js"></script>Module scripts:
- can use
importandexport; - are deferred automatically, so they run after the HTML is parsed;
- run in strict mode;
- have their own scope: top-level variables are not globals;
- must be served over HTTP. Opening the HTML file directly (
file:///) blocks module imports, so use a local server such as VS Code's Live Server extension.
Modules in Node.js#
Node.js supports two module systems:
const fs = require("fs");
module.exports = { withGst };New projects should use ES modules; you will still meet CommonJS in many existing packages and tutorials.
Built-in Node modules are imported with the node: prefix:
import { readFileSync } from "node:fs";
import path from "node:path";
console.log(path.extname("report.final.pdf"));
console.log(typeof readFileSync);.pdf
functionDynamic import()#
import() used as a function loads a module on demand and returns a promise. It is used to load heavy code only when it is needed (code splitting):
const { default: path } = await import("node:path");
console.log(path.basename("/photos/2026/goa.jpg"));goa.jpg// In a browser: load the chart library only when the user opens the chart
button.addEventListener("click", async () => {
const { drawChart } = await import("./chart.js");
drawChart(data);
});How modules behave#
- A module's code runs once, the first time it is imported. Every importer shares the same instance.
- Imports are live bindings: if a module changes an exported
let, importers see the new value. But importers cannot reassign an import. - Static
importstatements are hoisted and resolved before the module runs, which lets build tools remove unused code ("tree shaking").
Bundlers#
Large web apps often use a bundler or build tool (Vite, webpack, esbuild) that follows the imports, combines files, removes unused code and lets you import packages installed with npm by name, such as import { format } from "date-fns".
Practice#
Practice exercise
Split this code into two modules: validators.js, which exports isEmail and isStrongPassword as named exports, and main.js, which imports both and uses them. Then show how main.js would import everything from validators.js as one object instead.
function isEmail(s) { return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(s); }
function isStrongPassword(s) { return s.length >= 12; }
console.log(isEmail("asha@example.com"), isStrongPassword("short"));Show solution
export function isEmail(s) {
return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(s);
}
export function isStrongPassword(s) {
return s.length >= 12;
}import { isEmail, isStrongPassword } from "./validators.js";
console.log(isEmail("asha@example.com"), isStrongPassword("short")); // true falseimport * as validators from "./validators.js";
console.log(validators.isEmail("asha@example.com")); // trueKey takeaway#
Finished this lesson?