Menguasai URLPattern API: Membangun Routing dan Logika URL yang Cerdas di Browser
Sebagai developer web, kita sering berurusan dengan URL. Mulai dari membuat sistem routing di Single Page Application (SPA), mengekstrak parameter dari URL, hingga memastikan URL yang masuk ke backend memiliki format yang benar. Secara tradisional, pekerjaan ini sering melibatkan penggunaan Regular Expressions (regex) yang kompleks dan terkadang sulit dibaca atau di-maintain.
Tapi bagaimana jika ada cara yang lebih mudah, lebih deklaratif, dan bahkan merupakan standar web native untuk menangani semua itu?
Inilah saatnya Anda mengenal URLPattern API. 💡
1. Pendahuluan: Ucapkan Selamat Tinggal pada Regex URL yang Rumit!
Bayangkan Anda memiliki aplikasi web dengan berbagai rute dinamis, seperti /users/:id, /products/:category/:productId, atau bahkan URL dengan query string seperti /search?q=keyword&page=1. Bagaimana Anda biasanya menanganinya? Mungkin dengan String.prototype.match() atau RegExp.prototype.exec() yang hasilnya perlu Anda parse lagi secara manual.
// Contoh lama dengan regex
const path = "/users/123/profile";
const userPathRegex = /^\/users\/(\d+)\/profile$/;
const match = path.match(userPathRegex);
if (match) {
const userId = match[1];
console.log("User ID:", userId); // Output: User ID: 123
} else {
console.log("Path tidak cocok.");
}
Pendekatan ini bekerja, tetapi memiliki beberapa kelemahan:
- Keterbacaan: Regex bisa jadi mimpi buruk, terutama untuk pola yang kompleks.
- Parsing Manual: Anda harus secara manual mengekstrak grup tangkapan (capture groups) dari hasil regex.
- Kurang Fleksibel: Menggabungkan matching untuk pathname, search params, dan hash secara bersamaan menjadi sangat rumit.
URLPattern API hadir untuk menyederhanakan proses ini. Ia menyediakan cara deklaratif dan terstruktur untuk mendefinisikan pola URL, mencocokkan URL yang ada, dan mengekstrak informasi darinya, jauh lebih mudah dibaca dan dikelola daripada regex murni. Ini adalah standar web native, artinya Anda tidak perlu library pihak ketiga untuk menggunakannya di browser yang mendukung.
Mari kita selami lebih dalam!
2. Memahami Dasar URLPattern
Membuat URLPattern sangat mirip dengan membuat URL atau URLSearchParams. Anda cukup membuat instance baru dari URLPattern dengan pola URL yang Anda inginkan.
Pola ini bisa mencakup berbagai komponen URL: protocol, hostname, port, pathname, search, dan hash.
// Buat pola untuk URL
const userProfilePattern = new URLPattern({
pathname: "/users/:id/profile",
});
// Atau pola yang lebih lengkap
const fullProductPattern = new URLPattern({
protocol: "https",
hostname: "{subdomain}.example.com",
pathname: "/products/:category/:productId",
search: "?sort=:sortBy",
hash: "#section-:sectionId",
});
📌 Sintaks Pola:
:(Colon): Digunakan untuk mendefinisikan segmen URL dinamis (parameter). Misalnya,:idakan menangkap nilaiid.*(Asterisk): Wildcard tunggal yang cocok dengan satu segmen URL apa pun. Contoh:/files/*cocok dengan/files/document.pdftapi tidak/files/folder/document.pdf.**(Double Asterisk): Wildcard ganda yang cocok dengan nol atau lebih segmen URL. Contoh:/docs/**cocok dengan/docs/a,/docs/a/b, atau/docs.{}(Curly Braces): Digunakan untuk named groups, mirip dengan regex named capture groups, memungkinkan Anda menamai segmen yang cocok. Contoh:hostname: "{subdomain}.example.com"akan menangkapsubdomain.
Metode Penting: test() dan exec()
URLPattern memiliki dua metode utama untuk bekerja dengan URL:
-
pattern.test(url, baseURL?): Mengembalikantruejika URL cocok dengan pola,falsejika tidak. Ini adalah cara cepat untuk memeriksa kecocokan tanpa mengekstrak data.const pattern = new URLPattern({ pathname: "/articles/:slug" }); console.log(pattern.test("https://blog.example.com/articles/judul-artikel-keren")); // ✅ true console.log(pattern.test("https://blog.example.com/about")); // ❌ false -
pattern.exec(url, baseURL?): Mengembalikan objekURLPatternResultjika URL cocok, dannulljika tidak. ObjekURLPatternResultberisi semua informasi yang diekstrak dari URL, termasuk parameter dinamis. Ini adalah metode yang paling sering Anda gunakan untuk mendapatkan data dari URL.const pattern = new URLPattern({ pathname: "/users/:id/settings" }); const result = pattern.exec("https://app.example.com/users/456/settings"); if (result) { console.log(result.pathname.groups.id); // Output: 456 }
3. Ekstraksi Parameter Dinamis dengan Mudah
Salah satu kekuatan terbesar URLPattern adalah kemampuannya mengekstrak parameter dinamis dari URL secara otomatis. Parameter ini akan tersedia dalam objek groups di dalam properti komponen (pathname, search, hash, dll.) dari URLPatternResult.
const productDetailPattern = new URLPattern({
pathname: "/products/:category/:productId",
search: "?promo=:promoCode&ref=:referrerId?", // `?` setelah :referrerId berarti opsional
});
const url1 = "https://shop.example.com/products/electronics/laptop-x1?promo=BIGSALE&ref=partnerA";
const url2 = "https://shop.example.com/products/books/novel-fantasi?promo=FREESHIP";
const url3 = "https://shop.example.com/products/clothing/tshirt"; // Tidak cocok dengan search
const result1 = productDetailPattern.exec(url1);
const result2 = productDetailPattern.exec(url2);
const result3 = productDetailPattern.exec(url3);
if (result1) {
console.log("URL 1:");
console.log(" Kategori:", result1.pathname.groups.category); // electronics
console.log(" Product ID:", result1.pathname.groups.productId); // laptop-x1
console.log(" Promo Code:", result1.search.groups.promoCode); // BIGSALE
console.log(" Referrer ID:", result1.search.groups.referrerId); // partnerA
}
if (result2) {
console.log("\nURL 2:");
console.log(" Kategori:", result2.pathname.groups.category); // books
console.log(" Product ID:", result2.pathname.groups.productId); // novel-fantasi
console.log(" Promo Code:", result2.search.groups.promoCode); // FREESHIP
console.log(" Referrer ID:", result2.search.groups.referrerId); // undefined (karena opsional)
}
if (!result3) {
console.log("\nURL 3 tidak cocok karena search parameter tidak ada atau tidak sesuai.");
}
Seperti yang Anda lihat, parameter seperti :category, :productId, :promoCode, dan :referrerId langsung diekstrak ke dalam objek groups yang mudah diakses. Ini jauh lebih bersih daripada memanipulasi array hasil regex.
4. Studi Kasus 1: Routing Frontend yang Lebih Bersih
Salah satu aplikasi paling jelas dari URLPattern adalah untuk routing di aplikasi frontend Anda. Daripada menulis logika regex yang rumit untuk setiap rute, Anda bisa mendefinisikannya secara deklaratif.
// router.js
const routes = [
{
pattern: new URLPattern({ pathname: "/" }),
handler: () => renderHomePage(),
},
{
pattern: new URLPattern({ pathname: "/products/:category/:id" }),
handler: (params) => renderProductPage(params.category, params.id),
},
{
pattern: new URLPattern({ pathname: "/users/:userId/profile" }),
handler: (params) => renderUserProfilePage(params.userId),
},
{
pattern: new URLPattern({ pathname: "/search" }),
handler: (params) => renderSearchPage(params.q), // params.q dari search string
},
];
function handleRouting() {
const currentUrl = window.location.href;
for (const route of routes) {
const match = route.pattern.exec(currentUrl);
if (match) {
// Menggabungkan semua grup dari pathname, search, hash, dll.
const allParams = {
...match.pathname.groups,
...match.search.groups,
...match.hash.groups,
};
route.handler(allParams);
return;
}
}
renderNotFoundPage();
}
// Contoh fungsi render (placeholder)
function renderHomePage() { console.log("Menampilkan halaman beranda."); }
function renderProductPage(category, id) { console.log(`Menampilkan produk ${id} dari kategori ${category}.`); }
function renderUserProfilePage(userId) { console.log(`Menampilkan profil pengguna ${userId}.`); }
function renderSearchPage(query) { console.log(`Menampilkan hasil pencarian untuk: ${query || 'kosong'}.`); }
function renderNotFoundPage() { console.log("Halaman tidak ditemukan."); }
// Event listener untuk perubahan URL (misalnya dari link atau history.pushState)
window.addEventListener("popstate", handleRouting);
document.addEventListener("DOMContentLoaded", handleRouting); // Initial load
// Contoh navigasi programatik
function navigateTo(path) {
window.history.pushState({}, "", path);
handleRouting();
}
// Coba navigasi
// navigateTo("/");
// navigateTo("/products/books/123");
// navigateTo("/users/john.doe/profile");
// navigateTo("/search?q=javascript+tutorials");
// navigateTo("/non-existent-page");
✅ Dengan URLPattern, logika routing Anda menjadi lebih deklaratif, mudah dibaca, dan jauh lebih rapi. Anda bisa dengan cepat melihat pola URL dan parameter apa yang akan diekstrak.
5. Studi Kasus 2: Validasi dan Normalisasi URL
Selain routing, URLPattern juga sangat berguna untuk validasi URL. Anda bisa menggunakannya untuk memastikan URL yang dikirimkan pengguna atau diterima dari sumber eksternal sesuai dengan format yang diharapkan.
const allowedImagePattern = new URLPattern({
protocol: "https",
hostname: "{domain}.cdn.example.com",
pathname: "/images/**.{png|jpg|jpeg|gif}", // Menggunakan regex di dalam kurung kurawal untuk ekstensi
});