Module adalah satu file JavaScript yang membagikan sebagian isinya ke file lain. Bayangin dapur restoran: koki punya banyak bahan dan alat, tapi yang sampai ke meja tamu cuma piring yang dia taruh di jendela pengambilan. Yang gak ditaruh di jendela tetap di dapur. Di Node, jendela itu namanya export, dan file lain mengambil dari jendela itu dengan import.
🧪 Tebakan cepat:
catatan.jscuma meng-exportsemua, tapiapp.jsmemanggilcari(2). Apa yang terjadi? Tebak dulu, jawabannya ada di bagian "Yang gak di-export tetap di dalam file".
Satu file, satu module
Proyek catatan-api mulai tumbuh. Data catatan dan fungsi untuk mengambilnya kita pindah ke file sendiri, catatan.js, supaya app.js tetap pendek. Tiap file di Node punya ruang sendiri: variabel di catatan.js gak kelihatan dari app.js, kecuali di-export.
Node punya dua cara menulis module: CommonJS (cara asli Node, pakai require) dan ES Modules (standar JavaScript, pakai import, sama dengan yang dipakai browser).
CommonJS: module.exports dan require
// catatan.js
const catatan = [
{ id: 1, judul: "Belanja", isi: "beli beras 5 kg" },
{ id: 2, judul: "Belajar", isi: "bab Node.js" },
];
function semua() {
return catatan;
}
function cari(id) {
return catatan.find((c) => c.id === id);
}
module.exports = { semua, cari };
// app.js
const { semua, cari } = require("./catatan");
console.log(semua().length + " catatan");
console.log(cari(2).judul);
$ node app.js
2 catatan
Belajar
module.exports = { semua, cari }menaruh dua fungsi di jendela. Arraycatatangak ikut, jadi tetap privat.require("./catatan")menjalankancatatan.jslalu mengembalikan isimodule.exports-nya../artinya "di folder yang sama", dan di CommonJS ekstensi.jsboleh gak ditulis.const { semua, cari } = ...mengambil dua fungsi itu dari object yang dikembalikan.
Ada juga jalan pintas exports: exports.tambah = (a, b) => a + b; menambahkan tambah ke object yang sama. File lain yang menulis const math = require("./math") lalu math.tambah(2, 3) mendapat 5.
Modul bawaan Node di-require dengan namanya saja, tanpa ./: require("fs"), atau require("node:fs") supaya jelas itu bawaan Node.
Yang gak di-export tetap di dalam file
Ganti baris terakhir catatan.js jadi module.exports = { semua };, lalu jalankan lagi:
2 catatan
/home/budi/catatan-api/app.js:4
console.log(cari(2).judul);
^
TypeError: cari is not a function
require mengembalikan { semua } saja, jadi cari di app.js isinya undefined, dan memanggil undefined itu error. Baris 3 sempat jalan, program berhenti di baris 4. Itu jawaban tebakannya.
ES Modules: export dan import
File yang sama dengan sintaks ES Modules:
// catatan.js
export function semua() { return catatan; }
export function cari(id) { return catatan.find((c) => c.id === id); }
// app.js
import { semua, cari } from "./catatan.js";
Dua aturan yang beda dari CommonJS:
- Ekstensi wajib.
from "./catatan"tanpa.jsgagal denganError [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/budi/catatan-api/catatan', lalu Node menyarankanDid you mean to import "./catatan.js"? - Dicek sebelum jalan. Kalau
carigak di-export, gak ada satu baris pun yang jalan:SyntaxError: The requested module './catatan.js' does not provide an export named 'cari'.
Satu file juga bisa punya satu default export: export default function sapa() {...} diambil dengan import sapa from "./sapa.js";, tanpa kurung kurawal.
package.json yang memilih jenisnya
File .js dibaca sebagai CommonJS atau ES Modules menurut kolom "type" di package.json:
"type" |
.js dibaca sebagai |
Kalau salah tulis |
|---|---|---|
"commonjs" |
CommonJS | import gagal: SyntaxError: Cannot use import statement outside a module |
"module" |
ES Modules | require gagal: ReferenceError: require is not defined in ES module scope, you can use import instead |
| gak ada | CommonJS, tapi kalau ketemu import/export dibaca ulang sebagai ES Modules |
jalan, dengan peringatan MODULE_TYPELESS_PACKAGE_JSON |
npm init -y di Node 24 menulis "type": "commonjs". Untuk proyek baru yang memakai import, ganti jadi "module". Satu file bisa juga memilih sendiri lewat ekstensinya: .cjs selalu CommonJS, .mjs selalu ES Modules.
Di latihan: dua file dalam satu editor
Latihannya cuma punya satu editor, jadi "dua file" ditulis di satu tempat: fungsi tambah(a, b) dan kurang(a, b), module.exports = { tambah, kurang };, lalu require('./module'). Simulatornya membuat require dengan path relatif mengembalikan module.exports file itu sendiri. Di laptopmu, pisahkan jadi math.js dan app.js. Hasil tambah(10, 3) adalah 13, dan kurang(10, 3) adalah 7.
⚠️ Jebakan yang sering ketemu
- Fungsi tanpa
return. Fungsi yang cuma menghitunga + btanpareturnmengembalikanundefined, dan itu yang ikut ter-export. - Menulis
exports = { tambah }. Itu mengganti variabelexportssaja, bukan isi jendelanya.requiretetap mendapat object kosong, danmath.tambah(2, 3)jadiTypeError: math.tambah is not a function. Pakaimodule.exports = { ... }atauexports.tambah = .... - Lupa
.jsdiimport. CommonJS memaafkan, ES Modules gak. - Mencampur
requiredanimportdi satu file. Pilih satu jenis untuk satu proyek, sesuai"type".
TL;DR: Tiap file adalah module dengan ruangnya sendiri, dan cuma yang di-export yang bisa dipakai file lain. CommonJS: module.exports = { semua, cari } (atau exports.nama = ...) lalu const { semua } = require("./catatan"), ekstensi boleh gak ditulis, modul bawaan dengan require("fs"). ES Modules: export lalu import { semua } from "./catatan.js", ekstensi wajib. "type" di package.json memilih jenisnya: "commonjs" atau "module". Nama yang gak di-export bikin TypeError: ... is not a function di CommonJS dan SyntaxError sebelum jalan di ES Modules.