Node.js and Express course menu
Node.js Modules: ES Modules vs CommonJS (import and require)
Organise Node.js code into modules: ES modules with import and export, named and default exports, the node: prefix for built-in modules, CommonJS with require and module.exports, choosing between them with package.json type, and import.meta.dirname.
On this page
Real programs are split into many files. Each file is a module with its own scope: variables in one file are invisible to others unless they are exported. Node.js supports two module systems: modern ES modules (ESM, import/export, the JavaScript standard) and the older CommonJS (require/module.exports), which you will still meet in many existing projects.
ES modules#
Tell Node to treat .js files as ES modules with "type": "module" in package.json:
{
"type": "module"
}A module with named exports:
export const GST_RATE = 0.18;
export function withGst(amount) {
return Math.round(amount * (1 + GST_RATE) * 100) / 100;
}
export function formatRupees(amount) {
return `₹${amount.toLocaleString("en-IN", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}and one with a default export:
import { withGst } from "./pricing.js";
export default function cartTotal(items) {
const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0);
return withGst(subtotal);
}Using them:
import cartTotal from "./cart.js";
import { GST_RATE, formatRupees } from "./pricing.js";
const items = [
{ name: "Notebook", price: 60, qty: 3 },
{ name: "Pen", price: 25, qty: 4 },
];
console.log(`GST rate: ${GST_RATE * 100}%`);
console.log("Total:", formatRupees(cartTotal(items)));node app.jsGST rate: 18%
Total: ₹330.40Rules worth remembering:
- Relative imports need the file extension:
"./pricing.js", not"./pricing". - A module can have many named exports but only one default export. Named imports use braces and the exact names (rename with
as:import { withGst as addTax }); a default import can use any name. - Each module runs once, the first time it is imported; later imports share the same exported values.
Built-in modules and the node: prefix#
Node's own modules are imported the same way. The node: prefix makes clear it is a built-in, not a package from npm:
import { readFile } from "node:fs/promises";
import path from "node:path";
import os from "node:os";
console.log(path.extname("report.final.pdf"));
console.log(typeof readFile);
console.log(os.EOL === "\n" || os.EOL === "\r\n");.pdf
function
trueThe file's own folder#
In ES modules, import.meta.dirname is the folder of the current file and import.meta.filename its full path, useful for reading files that sit next to your code regardless of where node was started:
import path from "node:path";
const dataFile = path.join(import.meta.dirname, "data", "products.json");
console.log(path.basename(dataFile));
console.log(path.basename(import.meta.filename));node where.jsproducts.json
where.jsCommonJS#
CommonJS uses require() to import and module.exports to export. It is the default when package.json has no "type" (or "type": "commonjs"), and for files ending in .cjs:
function greet(name) {
return `Namaste, ${name}!`;
}
module.exports = { greet };const { greet } = require("./greet.cjs");
const path = require("node:path");
console.log(greet("Ravi"));
console.log(path.basename(__filename));node main.cjsNamaste, Ravi!
main.cjsCommonJS has __dirname and __filename built in; ES modules use import.meta.dirname and import.meta.filename instead.
Which should you use?#
Use ES modules for new projects; this course does. Current Node versions can also require() most ES modules, and ES modules can import CommonJS packages, so mixing is usually possible.
Common mistakes#
Practice#
Practice exercise
Create temperature.js exporting toFahrenheit(c) and toCelsius(f) (rounded to 1 decimal), and an index.js that imports both and prints 37 °C in Fahrenheit and 212 °F in Celsius.
Show hint
export function toFahrenheit(c) { return Math.round((c * 9 / 5 + 32) * 10) / 10; }, and import with import { toFahrenheit, toCelsius } from "./temperature.js";.
Show solution
export function toFahrenheit(c) {
return Math.round(((c * 9) / 5 + 32) * 10) / 10;
}
export function toCelsius(f) {
return Math.round((((f - 32) * 5) / 9) * 10) / 10;
}import { toCelsius, toFahrenheit } from "./temperature.js";
console.log(`37 °C = ${toFahrenheit(37)} °F`);
console.log(`212 °F = ${toCelsius(212)} °C`);node index.js37 °C = 98.6 °F
212 °F = 100 °CKey takeaway#
Finished this lesson?