REPL memang nyaman untuk eksperimen, tetapi kode program sungguhan perlu disimpan agar bisa dijalankan berulang kali, dibagikan, dan dirawat bersama. Di Node.js, wadah kode itu adalah berkas JavaScript biasa yang kita eksekusi lewat satu perintah node diikuti nama berkasnya. Chapter ini membawa kita membuat berkas pertama, menjalankannya, lalu membedakan tiga ekstensi yang sering kita jumpai — .js, .mjs, dan .cjs — beserta dua gaya module yang menyertainya.
Berkas JavaScript Pertama #
Buat sebuah berkas bernama salam.mjs di folder kerja kita, lalu isi dengan kode berikut:
const nama = "Budi";
const bahasa = "JavaScript";
console.log(`Halo, ${nama}!`);
console.log(`Kode ${bahasa} ini dijalankan dari sebuah berkas.`);Selanjutnya, buka terminal di folder yang sama dengan berkas tersebut, lalu jalankan:
node salam.mjsOutput yang Dihasilkan:
Halo, Budi!
Kode JavaScript ini dijalankan dari sebuah berkas.Mari kita telaah isi berkasnya baris per baris:
- Baris 1-2 (
const nama = ...): dua variable dideklarasikan denganconst— satu menyimpan string"Budi", satu lagi"JavaScript". - Baris 4-5 (
console.log(...)): dua baris cetakan memakai template literal — string ber backtick yang menyisipkan nilai lewat${...}. Tanda kurung kurawal di dalam backtick menunjuk nama variable yang nilainya ingin disisipkan. - Susunan keseluruhan: tidak ada function, tidak ada
main()khusus — Node.js membaca berkas dari baris pertama hingga terakhir dan mengeksekusinya berurutan. Struktur sederhana inilah bentuk paling dasar program Node.js.
Perintah node salam.mjs juga menerima path relatif, misalnya node latihan/salam.mjs, asalkan path tersebut benar dari posisi terminal kita berada. Node.js tidak peduli folder mana kode disimpan; yang dibutuhkan hanyalah path menuju berkasnya.
Tiga Ekstensi: .js, .mjs, dan .cjs #
Sejauh ini kita memakai .mjs. Lalu kapan muncul .js dan .cjs? Ketiga ekstensi itu menandai sistem module yang dipakai berkas tersebut — cara berkas saling berbagi kode. Ringkasannya seperti tabel berikut:
| Ekstensi | Sistem module | Perlakuan Node.js |
|---|---|---|
.mjs | ES Modules | selalu diperlakukan sebagai ES Modules, apa pun konfigurasinya |
.cjs | CommonJS | selalu diperlakukan sebagai CommonJS, apa pun konfigurasinya |
.js | tergantung package.json | mengikuti field "type" pada package.json terdekat; tanpa package.json, berkas .js diperlakukan sebagai CommonJS |
Dua sistem module tersebut punya dua kata kunci berbeda untuk saling memanggil kode: import milik ES Modules dan require milik CommonJS. Berikut penampilan pertama keduanya.
ES Modules: Mengimpor dengan import #
Pecah kode menjadi dua berkas. Berkas pertama, sapa.mjs, berisi function yang diekspor:
export function sapa(nama) {
return `Selamat belajar, ${nama}!`;
}Berkas kedua, utama.mjs, mengimpor function tersebut lalu memakainya:
import { sapa } from "./sapa.mjs";
console.log(sapa("Siti"));Jalankan berkas utamanya:
node utama.mjsOutput yang Dihasilkan:
Selamat belajar, Siti!Dua baris kunci pada pola ini perlu dibedah:
- Baris 1 di
utama.mjs(import { sapa } from "./sapa.mjs"): statementimportmengambil nilai yang diekspor berkas lain. Kurung kurawal berisi nama yang sama persis dengan kata kunciexportdisapa.mjs, dan path"./sapa.mjs"menunjuk berkas tersebut secara relatif — awalan./berarti “di folder yang sama”. - Baris 1 di
sapa.mjs(export function sapa(...)): kata kunciexportmenandai function agar bisa diimpor berkas lain. Function yang tidak diekspor tetap berjalan, tetapi hanya dikenal di dalam berkasnya sendiri.
Ketika node utama.mjs dijalankan, Node.js membaca utama.mjs, menemukan statement import, memuat sapa.mjs terlebih dahulu, baru mengeksekusi sisa kode. Urutan ini dijamin selesai sebelum baris console.log dieksekusi.
CommonJS: Mengimpor dengan require #
Sistem yang lebih lawas, CommonJS, memakai require dan module.exports. Berkas sapa.cjs berisi function yang sama, tetapi cara mengekspornya berbeda:
function sapa(nama) {
return `Selamat belajar, ${nama}!`;
}
module.exports = { sapa };Berkas pemanggilnya, utama.cjs, memuat function tersebut lewat require:
const { sapa } = require("./sapa.cjs");
console.log(sapa("Dewi"));Jalankan seperti biasa:
node utama.cjsOutput yang Dihasilkan:
Selamat belajar, Dewi!Mekanismenya paralel dengan versi ES Modules: module.exports = { sapa } menyerahkan object berisi function sapa kepada sistem module, lalu require("./sapa.cjs") mengembalikan object yang sama di sisi pemanggil. Notasi const { sapa } = ... lalu mengambil property sapa dari object tersebut ke sebuah variable. Hasil akhirnya identik — string Selamat belajar, Dewi! tercetak — hanya bahasa pengantar antar-berkasnya yang berbeda.
Menjalankan Ulang Otomatis dengan –watch #
Saat mengembangkan program, kita pasti berulang kali menyimpan berkas lalu menjalankan ulang perintah node. Node.js menyediakan opsi --watch yang mengotomatiskan siklus itu:
node --watch salam.mjsDengan opsi tersebut, Node.js menjalankan salam.mjs, lalu tetap berjalan di latar depan dan mengawasi perubahan berkas. Setiap kali kita menyimpan perubahan pada berkas yang berjalan, Node.js memuat ulang program secara otomatis sehingga versi terbaru langsung dieksekusi. Sesi pengawasan diakhiri dengan menekan Ctrl+C. Opsi ini paling terasa manfaatnya ketika kode kita tumbuh panjang dan sering diubah — kita akan memakainya rutin saat membangun proyek pada bagian akhir Course ini.
Kita kini bisa menyimpan kode dalam berkas, memecahnya menjadi module, dan menjalankannya dengan atau tanpa pengawasan otomatis. Pekerjaan selanjutnya adalah memilih tempat mengetik kode itu setiap hari — Chapter Memilih Code Editor memandu kita menimbang pilihan yang ada.