Tidak semua module menawarkan sekumpulan utilitas yang setara. Ada module yang berdiri di sekitar satu nilai utama: satu fungsi sapaan untuk kasir, satu objek konfigurasi, satu class khusus. Untuk pola semacam itu, JavaScript menyediakan default export — penawaran yang menyatakan “inilah isi utama module ini” dan memberi keleluasaan pada pengimpor untuk menamainya sendiri.
Chapter ini membahas cara menulis default export, menggabungkannya dengan named export dalam satu baris impor, dan mempertimbangkan kapan default layak dipilih dibanding named export.
Satu Nilai Utama per Module #
Default export ditulis dengan kata default setelah export, dan satu module hanya boleh memilikinya satu buah — menulis export default dua kali dalam berkas yang sama ditolak JavaScript sebagai SyntaxError. Berkas sapaan.mjs berikut menjadikan fungsi sapa sebagai nilai utamanya, dengan satu konstanta kecil sebagai pelengkap bernama:
// sapaan.mjs — satu nilai utama: fungsi sapa untuk kasir
export default function sapa(nama) {
return "Selamat datang di Kopi Senja, " + nama + "!";
}
export const VERSI = "1.0";Fungsi sapa tetap memiliki nama sendiri — penamaan ini membantu saat membaca stack trace — tetapi bagi luar module, fungsi tersebut dikenal sebagai default-nya sapaan.mjs, bukan sebagai nama sapa.
Default export tidak wajib berupa deklarasi fungsi bernama. Bentuk ekspresi juga sah: export default function (nama) { ... } tanpa nama fungsi, atau export default { host: "localhost", port: 3000 }; untuk objek konfigurasi. Meski begitu, menamai fungsi internal sebagaimana sapaan.mjs tetap menjadi kebiasaan yang baik — nama itu muncul pada stack trace saat terjadi galat, dan membuat isi berkas lebih mudah dibaca tanpa membayangkan dulu nama pengimpornya.
Mengimpor Default dengan Nama Bebas #
Ciri paling terlihat dari default export ada di sisi pengimpor: nama yang ditulis di depan koma sepenuhnya ditentukan berkas pengimpor, tanpa kurung kurawal. Perbandingan dengan named export terasa jelas di sini: { VERSI } wajib menyebut nama yang persis ditawarkan module, sedangkan nama sapaPembeli tidak pernah ada di sapaan.mjs — dan justru kebebasan itulah yang membuatnya sah. Berkas utama.mjs mengimpor keduanya sekaligus:
// utama.mjs — default dan named diimpor sekaligus
import sapaPembeli, { VERSI } from './sapaan.mjs';
console.log(sapaPembeli("Budi"));
console.log(sapaPembeli("Siti"));
console.log("versi module: " + VERSI);Output yang Dihasilkan:
Selamat datang di Kopi Senja, Budi!
Selamat datang di Kopi Senja, Siti!
versi module: 1.0Mari kita telaah baris-baris pentingnya:
- Baris 2 (
import sapaPembeli, { VERSI } ...): satu pernyataan impor memuat dua jenis nilai. Di depan koma,sapaPembelimenangkap default; di belakang koma,{ VERSI }mengambil named export dengan nama aslinya. - Baris 4–5 (
console.log(sapaPembeli(...));): fungsi default dipanggil seperti fungsi biasa. NamasapaPembelitidak ada disapaan.mjs— nama itu sepenuhnya kreasi pengimpor. Bagian teksSelamat datang di Kopi Senjadatang dari module, sedangkan nama penerima dikirim sebagai argumen oleh pemanggil. - Baris 7 (
console.log("versi module: " + VERSI);): named export tetap mengikuti aturan chapter sebelumnya — namanya harus persis sama dengan yang ditawarkan module.
Sifat “nama bebas” ini adalah kontrak default export. Kedua penulisan berikut sama-sama sah dan menangkap fungsi yang sama:
import salamPembuka from './sapaan.mjs';
import cekSapaan from './sapaan.mjs';Bentuk penulisan tersebut legal karena masing-masing pernyataan hanya membuat nama lokal baru untuk nilai default yang sama. Bila ingin tetap memakai sintaks kurung kurawal, default juga dapat diimpor lewat nama khusus default yang di-alias:
import { default as salamPembuka } from './sapaan.mjs';Bentuk Alternatif: export { ... as default } #
Baris export default function sapa(...) bukan satu-satunya cara menandai nilai utama. Kata default juga dapat dipakai di dalam daftar export, sebagaimana kata as pada named export — dan bentuk ini berjalan persis sama:
function sapa(nama) {
return "Selamat datang di Kopi Senja, " + nama + "!";
}
export const VERSI = "1.0";
export { sapa as default };Bentuk terakhir itu setara dengan export default function sapa(...) pada berkas asli: pengimpor tetap menulis import sapaPembeli, { VERSI } from './sapaan.mjs'; tanpa perubahan apa pun dan mendapatkan fungsi yang sama. Perbedaannya hanya letak kata default — menempel pada deklarasi, atau berada di daftar export di akhir berkas. Beberapa tim memilih bentuk kedua karena seluruh isi API module terbaca di satu tempat, konsisten dengan gaya daftar export pada chapter sebelumnya.
Kapan Memakai Default #
Pilihan antara default dan named sebaiknya mengikuti bentuk module itu sendiri:
- Default cocok untuk module yang punya satu nilai dominan: satu komponen antarmuka, satu class utama, satu objek konfigurasi. Penawarannya menyatakan maksud tersebut secara eksplisit.
- Named cocok untuk module berisi banyak utilitas setara, seperti
matematika.mjspada chapter sebelumnya. Pengimpor langsung terbaca mengambil apa saja. - Keduanya boleh hidup berdampingan dalam satu module, sebagaimana
sapaan.mjs— default untuk nilai utama, named untuk pelengkap seperti konstanta versi. - Default adalah konvensi umum pustaka. Banyak pustaka menawarkan satu komponen atau satu fungsi utama sebagai default dan melengkapi sisanya sebagai named export — pola yang memudahkan pengguna pustaka menemukan pintu utamanya sekaligus membaca daftar pelengkapnya.
Sisi lain yang perlu diwaspadai: default tidak diperiksa berdasarkan nama saat pengimpor menulisnya, sehingga kesalahan arah lebih mudah terjadi. Mengimpor default dari module yang tidak memilikinya ditolak Node dengan pesan tegas saat program dimuat — untuk sapaan.mjs yang memang punya default, contoh aman; tetapi bila tarif.mjs dari chapter pertama diimpor dengan import x from './tarif.mjs', Node menolaknya dengan SyntaxError: The requested module './tarif.mjs' does not provide an export named 'default'.
Default export menyelesaikan pertanyaan “nilai utama module ini apa”. Kini section ini memiliki dua bentuk penawaran yang saling melengkapi: named untuk banyak nilai dan default untuk satu nilai utama. Sisi pengimpor masih menyimpan beberapa bentuk impor lain yang belum kita sentuh — penggantian nama dengan as, impor seluruh isi module sekaligus, dan impor yang sengaja tanpa pengambilan nilai — dan ketiganya adalah topik chapter berikutnya.