URLPattern API: Routen-Matching ohne Regex-Bibliothek
AI generated
JS
() =>
JavaScript · Browser-APIs · Routing
URLPattern API
Routen-Matching ohne Regex-Bibliothek

Ein selbstgebauter Router besteht meist aus einem Wald von Regex-Mustern, die pfadgenau URLs erkennen und Parameter extrahieren sollen, kaum lesbar und fehleranfaellig bei Sonderzeichen. Die URLPattern API loest genau dieses Problem deklarativ und nativ im Browser.

15 Min. Lesezeit URLPattern API Routing Service Worker Pattern Matching

1. Das Problem mit handgeschriebenen Regex-Routern

Wer schon einmal einen eigenen Router fuer eine Single-Page-App oder einen Service Worker geschrieben hat, kennt das Muster: Ein Pfad wie /produkte/:id/bewertungen/:reviewId wird in ein Regex wie /^\/produkte\/([^/]+)\/bewertungen\/([^/]+)$/ uebersetzt, samt manueller Gruppen-Zuordnung ueber match[1], match[2] und so weiter. Das funktioniert, ist aber schwer lesbar, fehleranfaellig bei URL-kodierten Sonderzeichen und macht Code-Reviews unnoetig muehsam.

Die URLPattern API loest dieses Problem, indem sie eine deklarative, an bekannte Router-Syntax wie Express oder Vue Router angelehnte Musterschreibweise direkt als Browser-Standard bereitstellt. Aus /produkte/:id/bewertungen/:reviewId wird ein sprechendes Pattern-Objekt, das Named Groups automatisch extrahiert, ganz ohne selbst geschriebenen Regex.

2. Grundlagen: ein URLPattern-Objekt erzeugen und pruefen

Ein URLPattern wird mit einem Objekt aus URL-Komponenten instanziiert, meist genuegt pathname, kann aber auch protocol, hostname, port, search und hash umfassen, um komplette URLs statt nur Pfade zu matchen. Die einfachste Pruefung erfolgt ueber pattern.test(url), das lediglich true oder false zurueckliefert, ob eine gegebene URL zum Muster passt.

Fuer die eigentliche Extraktion von Parametern liefert pattern.exec(url) ein detailliertes Ergebnisobjekt oder null, wenn kein Match vorliegt. Dieses Objekt enthaelt pro URL-Komponente ein groups-Feld mit den extrahierten Named-Group-Werten, sodass keine manuelle Indexierung wie bei klassischen Regex-Matches noetig ist.


// Einfaches Pattern erzeugen und pruefen
const pattern = new URLPattern({ pathname: '/produkte/:id' });

console.log(pattern.test('https://mironsoft.de/produkte/42')); // true
console.log(pattern.test('https://mironsoft.de/kategorien/42')); // false

const result = pattern.exec('https://mironsoft.de/produkte/42');
console.log(result.pathname.groups.id); // "42"

3. Named Groups: Parameter deklarativ extrahieren

Named Groups sind das zentrale Werkzeug fuer parametrisierte Routen. Ein Doppelpunkt gefolgt von einem Bezeichner, etwa :id oder :slug, definiert eine benannte Gruppe, die einen beliebigen Pfadsegment-Wert erfasst und unter genau diesem Namen im groups-Objekt des exec()-Ergebnisses auftaucht. Mehrere Named Groups in einem Pattern werden unabhaengig voneinander extrahiert.

Anders als bei per Hand geschriebenen Regex-Gruppen ist die Reihenfolge dabei irrelevant, es zaehlt ausschliesslich der Name. Das macht Refactorings deutlich sicherer: Wird eine Named Group innerhalb des Patterns verschoben oder eine weitere davor eingefuegt, bleibt der Zugriffscode ueber groups.id unveraendert korrekt, waehrend bei numerisch indizierten Regex-Gruppen jede Verschiebung alle nachfolgenden Indizes verschoben haette.


// Mehrere Named Groups in einem Pattern
const pattern = new URLPattern({
  pathname: '/produkte/:category/:id/bewertungen/:reviewId',
});

const result = pattern.exec('https://mironsoft.de/produkte/laptops/42/bewertungen/7');

console.log(result.pathname.groups);
// { category: 'laptops', id: '42', reviewId: '7' }

4. Wildcards und optionale Segmente

Neben Named Groups unterstuetzt die URLPattern API Wildcards ueber den Stern (*), der eine beliebige Anzahl an Zeichen inklusive Schraegstrichen erfasst, praktisch fuer Catch-All-Routen wie statische Datei-Server oder 404-Fallbacks. Ein Muster wie /assets/* matcht jeden Pfad, der mit /assets/ beginnt, unabhaengig davon, wie viele weitere Segmente folgen.

Optionale Segmente werden mit einem Fragezeichen nach der Gruppe markiert, etwa /blog/:slug? erfasst sowohl /blog als auch /blog/mein-artikel. Diese Syntax orientiert sich bewusst an bereits etablierten Router-Bibliotheken wie path-to-regexp, sodass Entwickler mit Erfahrung in Express oder Vue Router sich sofort zurechtfinden, ohne die Spezifikation von Grund auf lernen zu muessen.


// Wildcard fuer Catch-All-Routen
const assetsPattern = new URLPattern({ pathname: '/assets/*' });
console.log(assetsPattern.test('https://mironsoft.de/assets/img/logo.svg')); // true

// Optionales Segment
const blogPattern = new URLPattern({ pathname: '/blog/:slug?' });
console.log(blogPattern.test('https://mironsoft.de/blog')); // true
console.log(blogPattern.test('https://mironsoft.de/blog/mein-artikel')); // true

5. Einsatz in einem Service-Worker-Router

Ein klassischer Einsatzort fuer die URLPattern API ist der fetch-Handler eines Service Workers, der je nach angefragter URL unterschiedliche Caching-Strategien anwenden soll, etwa Cache-First fuer Bilder, Network-First fuer API-Aufrufe und Stale-While-Revalidate fuer HTML-Seiten. Statt manuell mit startsWith() oder Regex zu pruefen, lassen sich Routen als Liste von URLPattern-Objekten mit zugehoeriger Strategie definieren.

Diese Struktur ist deutlich wartbarer als verschachtelte if/else-Bloecke, weil neue Routen einfach als weiterer Eintrag in der Liste ergaenzt werden, ohne bestehende Bedingungen anzufassen. Der fetch-Handler iteriert einmal ueber alle Routen und wendet die erste passende Strategie an, ein Muster, das sich fast identisch auch in einem Client-seitigen Router wiederverwenden laesst.


// sw.js: Routen-Tabelle mit URLPattern
const routes = [
  { pattern: new URLPattern({ pathname: '/assets/*' }), strategy: cacheFirst },
  { pattern: new URLPattern({ pathname: '/api/*' }), strategy: networkFirst },
  { pattern: new URLPattern({ pathname: '/*' }), strategy: staleWhileRevalidate },
];

self.addEventListener('fetch', (event) => {
  const route = routes.find((r) => r.pattern.test(event.request.url));
  if (route) {
    event.respondWith(route.strategy(event.request));
  }
});

6. Einsatz in einem Client-Router

Auf Client-Seite laesst sich die URLPattern API hervorragend mit der Navigation API kombinieren, um innerhalb eines navigate-Event-Handlers zu entscheiden, welche Route zustaendig ist und welche Parameter aus der URL extrahiert werden sollen. Statt eigener Parsing-Logik uebernimmt exec() sowohl das Matching als auch die Parameter-Extraktion in einem einzigen Aufruf.

Ein einfacher Router iteriert dabei ueber eine Konfigurationsliste aus Pattern und zugehoeriger Komponente, findet den ersten Treffer und uebergibt die extrahierten Named Groups direkt als Props an die zustaendige View-Funktion. Das reduziert Router-Implementierungen oft auf wenige Zeilen Kernlogik, der Rest ist reine Konfiguration.


// Einfacher Client-Router mit URLPattern
const routeTable = [
  { pattern: new URLPattern({ pathname: '/produkte/:id' }), view: renderProductView },
  { pattern: new URLPattern({ pathname: '/kategorien/:slug' }), view: renderCategoryView },
  { pattern: new URLPattern({ pathname: '/*' }), view: renderNotFoundView },
];

function resolveRoute(url) {
  for (const route of routeTable) {
    const match = route.pattern.exec(url);
    if (match) {
      return route.view(match.pathname.groups);
    }
  }
}

7. Direkter Vergleich zu handgeschriebenen Regex-Mustern

Der offensichtlichste Vorteil der URLPattern API ist Lesbarkeit: /produkte/:id/bewertungen/:reviewId ist auf einen Blick verstaendlich, waehrend das aequivalente Regex mit Escaping von Schraegstrichen und nicht-erfassenden Gruppen selbst fuer erfahrene Entwickler Aufmerksamkeit erfordert. Fehler wie ein vergessenes Escaping eines Punkts im Pfad fuehren bei Regex zu stillen Fehlern, die URLPattern-Syntax vermeidet diese Fallstricke von vornherein.

Der zweite Vorteil ist die eingebaute URL-Komponenten-Awareness: Ein URLPattern kann gleichzeitig protocol, hostname, port und pathname matchen, etwa um nur Anfragen von einer bestimmten Subdomain ueber HTTPS zu erfassen, waehrend ein aequivalentes Regex die komplette URL als einen einzigen String parsen und dabei URL-Encoding-Eigenheiten selbst beruecksichtigen muesste.

Ein dritter, oft unterschaetzter Punkt ist Testbarkeit: Da ein URLPattern-Objekt aus einer klaren Konfiguration besteht, laesst es sich in Unit-Tests einfach mit unterschiedlichen Beispiel-URLs pruefen, ohne dass Testautoren die Regex-Syntax selbst verstehen muessen. Ein Reviewer kann allein anhand der Pattern-Definition nachvollziehen, welche URLs matchen sollen, was bei einem rohen Regex haeufig erst durch Ausprobieren in der Konsole geklaert werden muss.

Schliesslich profitiert auch die Fehlersuche in Produktion: Landet eine URL versehentlich nicht im erwarteten Route-Zweig, laesst sich mit pattern.exec() im Browser-DevTools-Konsolenkontext sofort nachvollziehen, an welcher Stelle das Matching scheitert, waehrend ein aequivalentes Regex oft erst mit einem externen Regex-Tester analysiert werden muss, um die Ursache zu finden.

8. Browser-Unterstuetzung und Polyfill

Die URLPattern API ist in Chrome und Edge seit Version 95 nativ verfuegbar, in Firefox und Safari zum Zeitpunkt der Erstellung dieses Artikels noch nicht implementiert. Fuer den produktiven Einsatz in oeffentlich zugaenglichen Anwendungen ist deshalb ein Polyfill wie urlpattern-polyfill sinnvoll, das dieselbe API-Oberflaeche auf Basis eines eigenen Parsers bereitstellt.

Da das Polyfill dieselbe Konstruktor-Signatur und dieselben Methoden implementiert, laesst sich der Wechsel zwischen nativer API und Polyfill ueber ein einfaches Feature-Detection-Pattern am Anfang der Anwendung realisieren, ohne dass der restliche Router-Code angepasst werden muss.

In Service Workern ist besonders auf die Bundle-Groesse des Polyfills zu achten, da jeder zusaetzliche Import die Aktivierungszeit des Workers verlaengert. Es empfiehlt sich daher, das Polyfill nur dann zu laden, wenn die Feature-Detection tatsaechlich ein Fehlen der nativen API feststellt, statt es pauschal fuer alle Nutzer im Hauptbundle mitzuliefern.


// Polyfill nur laden, wenn die native API fehlt
async function ensureURLPattern() {
  if (typeof URLPattern === 'undefined') {
    await import('urlpattern-polyfill');
  }
}

await ensureURLPattern();
// ab hier ist URLPattern garantiert verfuegbar

9. Fazit: deklaratives Matching als Standardwerkzeug fuer Router

Die URLPattern API ersetzt handgeschriebene Regex-Router durch eine lesbare, standardisierte Syntax, die Named Groups automatisch extrahiert und dabei die kompletten URL-Komponenten beruecksichtigt statt nur einzelner Strings. Sowohl in Service-Worker-Routern fuer Caching-Strategien als auch in Client-Routern fuer SPA-Navigation reduziert sie Boilerplate deutlich.

Solange die Browser-Unterstuetzung nicht vollstaendig ist, bleibt ein Polyfill fuer Firefox und Safari empfehlenswert, doch die API-Oberflaeche selbst ist bereits der richtige Standard fuer neue Router-Implementierungen. Die folgende Tabelle vergleicht Kernaspekte zwischen URLPattern und handgeschriebenem Regex.

Aspekt Handgeschriebenes Regex URLPattern API Vorteil
Lesbarkeit Escaping, nicht-erfassende Gruppen Sprechende :name-Syntax Direkt verstaendlich ohne Regex-Kenntnis
Parameter-Extraktion Manuelle Indexierung ueber match[1] groups-Objekt mit Namen Robust gegen Refactoring
URL-Komponenten Kompletter String muss geparst werden protocol/hostname/pathname getrennt Praezises Matching einzelner Teile
Browser-Support Ueberall (reines JS) Chromium nativ, sonst Polyfill Regex als Fallback-Option nutzbar

Mironsoft

Moderne Browser-APIs, Performance und wartbares JavaScript

JavaScript, das im echten Browser robust bleibt, nicht nur im Tutorial?

Wir prüfen bestehenden Frontend-Code auf veraltete Patterns, unnötige Bibliotheken und Performance-Fallen und ersetzen sie durch moderne, native Browser-APIs, die weniger Bundle-Gewicht und weniger Wartungslast bedeuten.

Code-Review

Veraltete Patterns, unnötige Dependencies und Memory Leaks systematisch aufspüren.

Performance-Optimierung

Bundle-Größe, Ladezeit und Runtime-Performance mit modernen APIs verbessern.

Modernisierung

Native Browser-APIs statt schwerer Bibliotheken gezielt einführen.

10. Zusammenfassung

URLPattern API: Das Wichtigste auf einen Blick

Named Groups

:name-Syntax extrahiert Parameter automatisch ins groups-Objekt

Wildcards

Stern (*) und Fragezeichen (?) fuer Catch-All- und optionale Segmente

Einsatzorte

Service-Worker-Caching-Router und Client-seitige SPA-Router

Support

Nativ in Chromium, Polyfill fuer Firefox und Safari verfuegbar

11. FAQ: URLPattern API: Das Wichtigste auf einen Blick

1Was loest die URLPattern API im Vergleich zu Regex?
Sie ersetzt handgeschriebene Regex-Muster fuer URL-Matching durch eine lesbare, deklarative Syntax mit automatischer Parameter-Extraktion ueber Named Groups.
2Wie erzeuge ich Named Groups?
Mit einem Doppelpunkt gefolgt von einem Bezeichner im Pfad, etwa /produkte/:id. Der extrahierte Wert erscheint im groups-Objekt des exec()-Ergebnisses unter dem Namen id.
3Was ist der Unterschied zwischen test() und exec()?
test() liefert nur true oder false, ob eine URL zum Pattern passt. exec() liefert zusaetzlich das vollstaendige Match-Objekt mit allen extrahierten Named Groups oder null bei keinem Treffer.
4Wie definiere ich eine Catch-All-Route?
Mit einem Stern als Wildcard, etwa /assets/*, der eine beliebige Anzahl an Zeichen inklusive Schraegstrichen erfasst.
5Kann ich mit URLPattern auch Hostname oder Protokoll matchen?
Ja, das Pattern-Objekt kann neben pathname auch protocol, hostname, port, search und hash enthalten, um komplette URLs statt nur Pfade zu pruefen.
6Wie mache ich ein Segment optional?
Mit einem Fragezeichen nach der Named Group, etwa /blog/:slug?, das sowohl /blog als auch /blog/mein-artikel abdeckt.
7Wo wird die URLPattern API typischerweise eingesetzt?
In Service-Worker-Routern fuer unterschiedliche Caching-Strategien je nach URL sowie in Client-seitigen Routern fuer SPA-Navigation, oft in Kombination mit der Navigation API.
8Welche Browser unterstuetzen die API nativ?
Chrome und Edge seit Version 95. Firefox und Safari unterstuetzen sie zum Zeitpunkt der Erstellung dieses Artikels noch nicht nativ.
9Gibt es einen Polyfill fuer nicht unterstuetzende Browser?
Ja, urlpattern-polyfill implementiert dieselbe API-Oberflaeche und kann per Feature-Detection nur bei Bedarf nachgeladen werden.
10Ist die Syntax an bestehende Router-Bibliotheken angelehnt?
Ja, die :name-Syntax orientiert sich bewusst an etablierten Bibliotheken wie path-to-regexp, das unter anderem von Express und Vue Router verwendet wird.