Aplikasi Node.js sering berhadapan dengan alamat web: endpoint API milik layanan lain, tautan yang dikirim pengguna, sampai lokasi berkas dalam format file://. Memecah alamat semacam itu dengan split("?") atau regular expression memang bisa, tetapi aturan URL ternyata penuh detail — port, query string berulang, karakter yang perlu di-escape — dan satu saja yang terlewat, hasilnya salah. Module node:url menyediakan penguraian dan penyusunan URL yang mengikuti standar web, sehingga kode kita memakai parser yang sama dengan browser.
Mengurai URL dengan Class URL #
Class URL bisa diimpor dari node:url, dan karena URL juga merupakan global Node.js, class tersebut bahkan bisa dipakai tanpa import — sama seperti di browser. Constructor new URL() menerima satu string alamat, mengurainya, lalu menyimpan tiap bagian pada property yang mudah dibaca. Berkas urai-url.mjs membedah satu alamat halaman dokumentasi yang punya query string dan bagian hash:
import { URL } from "node:url";
const alamat = new URL(
"https://nodejs.org/api/url.html?format=markdown&tag=baru#bagian",
);
console.log("protocol:", alamat.protocol);
console.log("host :", alamat.host);
console.log("pathname:", alamat.pathname);
console.log("search :", alamat.search);
console.log("hash :", alamat.hash);
console.log("format :", alamat.searchParams.get("format"));
try {
new URL("bukan-url");
} catch (error) {
console.log("error :", error.name, "-", error.message);
}Output yang Dihasilkan:
protocol: https:
host : nodejs.org
pathname: /api/url.html
search : ?format=markdown&tag=baru
hash : #bagian
format : markdown
error : TypeError - Invalid URLMari kita telaah baris-baris kode di atas:
- Baris 3-5 (
new URL(...)): Satu string alamat diurai menjadi object. Propertyprotocol,host,pathname,search, danhashmenyimpan bagian-bagiannya —searchmasih mentah beserta tanda?,hashbeserta tanda#. - Baris 12 (
alamat.searchParams.get("format")): Setiap instanceURLotomatis membawa propertysearchParamsberupa objectURLSearchParams, sehingga nilai query string bisa langsung dibaca tanpa parsing tambahan. - Baris 14-18 (
try/catch): ConstructorURLmemvalidasi masukan — string yang bukan URL valid membuatTypeErrorterlempar, bukan object rusak yang lolos diam-diam. Validasi sejak pembuatan seperti ini membuat error terdeteksi dini, tepat di titik data masuk.
Karena URL adalah global, snippet pendek berikut berjalan tanpa satu baris import pun:
const alamat = new URL("https://nodejs.org/en/learn/#daftar");
console.log(typeof URL);
console.log(alamat.hostname);Output yang Dihasilkan:
function
nodejs.orgPerlu dicatat perbedaan dua property yang mirip: host menyimpan nama domain beserta port bila ada (example.com:8080), sedangkan hostname hanya nama domainnya. Dua-duanya berguna — pilih sesuai kebutuhan.
Query String dengan URLSearchParams #
Query string adalah bagian URL setelah tanda ?, dan strukturnya adalah daftar pasangan kunci-nilai — satu kunci boleh muncul lebih dari sekali. Class URLSearchParams mengelola daftar tersebut: bisa dibuat dari string query, dari property searchParams milik URL, lalu dimodifikasi dan dirangkai kembali. Berkas query-params.mjs memperlihatkan operasi yang paling sering dipakai:
import { URLSearchParams } from "node:url";
const params = new URLSearchParams("status=selesai&tag=pekerjaan&tag=penting");
console.log("get :", params.get("status"));
console.log("getAll :", params.getAll("tag"));
console.log("ada? :", params.has("halaman"));
params.set("status", "tertunda");
params.append("tag", "mendesak");
for (const [kunci, nilai] of params) {
console.log("pasangan:", kunci, "=", nilai);
}
console.log("toString:", params.toString());Output yang Dihasilkan:
get : selesai
getAll : [ 'pekerjaan', 'penting' ]
ada? : false
pasangan: status = tertunda
pasangan: tag = pekerjaan
pasangan: tag = penting
pasangan: tag = mendesak
toString: status=tertunda&tag=pekerjaan&tag=penting&tag=mendesakMari kita telaah baris-baris kode di atas:
- Baris 3: Object dibuat langsung dari string query. Kunci
tagsengaja muncul dua kali untuk memperlihatkan perilaku kunci berulang. - Baris 5-7:
get()mengambil nilai pertama,getAll()mengambil seluruh nilai dalam bentuk array, danhas()memeriksa keberadaan kunci tanpa mengambil nilainya. - Baris 9-10:
set()mengganti nilai kunci yang sudah ada di posisinya, sedangkanappend()menambahkan pasangan baru di akhir — dua operasi dengan hasil akhir yang berbeda. - Baris 12-14: Object ini bisa di-iterasi dengan
for...ofkarena merupakan iterable; tiap iterasi menghasilkan array[kunci, nilai], dan urutannya mengikuti urutan penyimpanan. - Baris 16 (
params.toString()): Seluruh pasangan dirangkai kembali menjadi string query yang siap ditempelkan ke URL, lengkap dengan penanganan karakter khusus.
Menyusun Kembali URL dengan format() #
Penguraian punya kebalikannya: menyusun URL dari bagian-bagian. Function format() menerima object berisi property protocol, host, pathname, dan search, lalu merangkainya menjadi satu alamat utuh:
import { format } from "node:url";
const bagian = {
protocol: "https:",
host: "nodejs.org",
pathname: "/api/url.html",
search: "?format=markdown",
};
console.log(format(bagian));Output yang Dihasilkan:
https://nodejs.org/api/url.html?format=markdownCara lain yang sama validnya adalah membuat new URL() lalu mengubah property-nya satu per satu; property href selalu berisi alamat hasil perubahan terbaru. format() unggul saat bagian-bagian datang dari data terpisah — misalnya konfigurasi host dan path dari environment variable — karena seluruh perakitan terjadi dalam satu panggilan function.
import.meta.url dan fileURLToPath() #
Ada satu pola khusus di ESM yang memakai module ini dan akan sering kita jumpai: import.meta.url. Pada setiap module ES, ekspresi tersebut berisi alamat file:// dari berkas module itu sendiri — semacam “alamat diri sendiri”. Dengan menjadikannya basis, kita bisa menghitung alamat berkas lain yang berada di sebelah module:
import { readFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import path from "node:path";
const urlTugas = new URL("./tugas.json", import.meta.url);
console.log("protokol:", urlTugas.protocol);
const lokasiTugas = fileURLToPath(urlTugas);
console.log("berkas :", path.basename(lokasiTugas));
const isi = await readFile(lokasiTugas, "utf8");
const tugas = JSON.parse(isi);
console.log("pelaku :", tugas.pelaku);
console.log("tugas :", tugas.kegiatan);Output yang Dihasilkan:
protokol: file:
berkas : tugas.json
pelaku : Siti
tugas : Menyusun laporan bulananMari kita telaah baris-baris kode di atas:
- Baris 5 (
new URL("./tugas.json", import.meta.url)): Argumen keduanew URL()adalah basis resolusi —./tugas.jsondihitung relatif terhadap lokasi berkasberkas-lokal.mjs, bukan direktori kerja tempat perintahnodedijalankan. Pola ini adalah padanan modern__dirnamedi CommonJS. - Baris 8 (
fileURLToPath(urlTugas)): Function ini mengubah URLfile://menjadi path berkas biasa yang dimengerti function lain sepertireadFile(). Hasilnya berupa path absolut menuju folder chapter ini — nilainya berbeda di setiap komputer, sehingga contoh sengaja hanya mencetakbasename()-nya. - Baris 11-14: Berkas
tugas.jsondibaca lalu diurai denganJSON.parse(). Modulenode:fsakan kita bedah tuntas pada Section Filesystem; untuk sekarang cukup ketahui bahwareadFile()mengembalikan isi berkas sebagai string.
Dengan node:path untuk berkas dan node:url untuk alamat, dua format “lokasi” utama sudah kita kuasai. Chapter berikutnya berpindah ke module perkakas serbaguna node:util — tempat kami menemukan utilitas untuk memproses argumen CLI, membungkus callback menjadi promise, hingga merapikan output debugging.
Referensi lanjutan untuk topik chapter ini: