Ein Ansatz zur Standardisierung häufiger Anwendungsfälle für Musterabgleiche.
Hintergrund
Das Routing ist ein wichtiger Bestandteil jeder Webanwendung. Beim Routing wird eine URL verwendet, auf die ein Musterabgleich oder eine andere appspezifische Logik angewendet wird. Anschließend werden in der Regel Webinhalte basierend auf dem Ergebnis angezeigt. Das Routing kann auf unterschiedliche Weise implementiert werden: Manchmal ist es Code, der auf einem Server ausgeführt wird und einen Pfad zu Dateien auf dem Laufwerk zuordnet, oder Logik in einer Single-Page-App, die auf Änderungen am aktuellen Standort wartet und ein entsprechendes DOM-Element zum Anzeigen erstellt.
Es gibt zwar keinen eindeutigen Standard, aber Webentwickler haben sich für eine gemeinsame Syntax zum Ausdruck von URL-Routing-Mustern entschieden, die viel mit regular expressions
gemeinsam haben, aber einige domainspezifische Ergänzungen wie Tokens zum Abgleichen von Pfadsegmenten enthalten.
Gängige serverseitige Frameworks wie Express und Ruby on Rails verwenden diese Syntax (oder eine sehr ähnliche) und JavaScript-Entwickler können Module wie path-to-regexp
oder regexpparam
verwenden, um diese Logik in ihren eigenen Code einzufügen.
URLPattern
ist eine Ergänzung der Webplattform, die auf der Grundlage dieser Frameworks aufbaut. Ziel ist es, eine Routing-Mustersyntax zu standardisieren, einschließlich Unterstützung für Platzhalter, benannte Tokengruppen, reguläre Ausdrucksgruppen und Gruppenmodifikatoren. Mit dieser Syntax erstellte URLPattern
-Instanzen können gängige Routingaufgaben ausführen, z. B. den Abgleich mit vollständigen URLs oder einer URL vom Typ pathname
und das Zurückgeben von Informationen zu den Token- und Gruppenübereinstimmungen.
Ein weiterer Vorteil der URL-Übereinstimmung direkt auf der Webplattform besteht darin, dass eine gemeinsame Syntax dann für andere APIs verwendet werden kann, die ebenfalls mit URLs abgeglichen werden müssen.
Browserunterstützung und Polyfills
URLPattern
ist in Chrome und Edge ab Version 95 standardmäßig aktiviert.
Die Bibliothek urlpattern-polyfill
bietet eine Möglichkeit, die URLPattern
-Oberfläche in Browsern oder Umgebungen wie Node zu verwenden, die keine integrierte Unterstützung bieten. Wenn Sie die Polyfill verwenden, sollten Sie die Feature-Erkennung verwenden, damit sie nur geladen wird, wenn die aktuelle Umgebung nicht unterstützt wird. Andernfalls verlieren Sie einen der Hauptvorteile von URLPattern
: In Supportumgebungen muss kein zusätzlicher Code heruntergeladen und geparst werden, um ihn zu verwenden.
if (!(globalThis && 'URLPattern' in globalThis)) {
// URLPattern is not available, so the polyfill is needed.
}
Syntaxkompatibilität
Eine Leitphilosophie für URLPattern
ist es, Neuentwicklungen zu vermeiden. Wenn Sie bereits mit der Routing-Syntax von Express oder Ruby on Rails vertraut sind, müssen Sie nichts Neues lernen. Aufgrund der leichten Abweichungen zwischen den Syntaxen in gängigen Routingbibliotheken musste jedoch eine Basissyntax ausgewählt werden. Die Designer von URLPattern
entschieden sich, die Mustersyntax von path-to-regexp
(nicht jedoch die API-Oberfläche) als Ausgangspunkt zu verwenden.
Diese Entscheidung wurde in enger Absprache mit dem aktuellen Administrator von path-to-regexp
getroffen.
Die Dokumentation zu path-to-regexp
ist die beste Informationsquelle für die unterstützte Syntax. Die Dokumentation, die auf der MDN veröffentlicht werden soll, finden Sie in ihrer aktuellen Version auf GitHub.
Zusätzliche Funktionen
Die Syntax von URLPattern
ist eine Übermenge dessen, was path-to-regexp
unterstützt, da URLPattern
eine unter Routingbibliotheken eher seltene Funktion unterstützt: das Abgleichen von Ursprüngen, einschließlich Platzhaltern in Hostnamen. Die meisten anderen Routingbibliotheken befassen sich nur mit dem pathname und gelegentlich mit dem Such- oder Hash-Teil einer URL. Sie müssen nie den Ursprungsteil einer URL prüfen, da sie nur für das Routing innerhalb einer eigenständigen Webanwendung verwendet werden.
Wenn Sie Ursprünge berücksichtigen, eröffnen sich zusätzliche Anwendungsfälle, z. B. das Weiterleiten von Anfragen zwischen verschiedenen Ursprüngen innerhalb des fetch
-Ereignishandlers eines Dienstarbeiters. Wenn Sie nur URLs mit demselben Ursprung weiterleiten, können Sie diese zusätzliche Funktion ignorieren und URLPattern
wie andere Bibliotheken verwenden.
Beispiele
Muster erstellen
Wenn Sie ein URLPattern
erstellen möchten, übergeben Sie dem Konstruktor entweder Strings oder ein Objekt, dessen Eigenschaften Informationen zum zu vergleichenden Muster enthalten.
Wenn Sie ein Objekt übergeben, können Sie am besten festlegen, welches Muster für die Übereinstimmung der einzelnen URL-Komponenten verwendet werden soll. Im schlimmsten Fall könnte das so aussehen:
const p = new URLPattern({
protocol: 'https',
username: '',
password: '',
hostname: 'example.com',
port: '',
pathname: '/foo/:image.jpg',
search: '*',
hash: '*',
});
Wenn Sie für eine Property einen leeren String angeben, wird nur dann eine Übereinstimmung gefunden, wenn der entsprechende Teil der URL nicht festgelegt ist. Der Platzhalter *
entspricht jedem Wert für einen bestimmten Teil der URL.
Der Konstruktor bietet mehrere Tastenkürzel für eine einfachere Verwendung. Wenn Sie search
und hash
oder andere Properties vollständig weglassen, entspricht das dem Festlegen der Platzhalter '*'
. Das obige Beispiel könnte so vereinfacht werden:
const p = new URLPattern({
protocol: 'https',
username: '',
password: '',
hostname: 'example.com',
port: '',
pathname: '/foo/:image.jpg',
});
Als zusätzliche Vereinfachung können alle Informationen zur Quelle in einer einzigen Property (baseURL
) angegeben werden.
const p = new URLPattern({
pathname: '/foo/:image.jpg',
baseURL: 'https://example.com',
});
Bei allen diesen Beispielen wird davon ausgegangen, dass Ihr Anwendungsfall Übereinstimmungen von Ursprüngen umfasst. Wenn Sie nur die Übereinstimmung mit den anderen Teilen der URL, ohne den Ursprung, anstreben (wie bei vielen „traditionellen“ Routingszenarien mit nur einem Ursprung), können Sie die Ursprungsinformationen vollständig weglassen und nur eine Kombination der Eigenschaften pathname
, search
und hash
angeben. Wie bisher werden ausgelassene Properties so behandelt, als wären sie auf das Platzhaltermuster *
festgelegt.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
Anstatt ein Objekt an den Konstruktor zu übergeben, können Sie einen oder zwei Strings angeben. Wenn ein String angegeben wird, sollte er ein vollständiges URL-Muster darstellen, einschließlich Musterinformationen, die zum Abgleich mit dem Ursprung verwendet werden. Wenn Sie zwei Strings angeben, wird der zweite String als baseURL
verwendet und der erste String wird relativ zu dieser Basis betrachtet.
Unabhängig davon, ob ein oder zwei Strings angegeben werden, wird das vollständige URL-Muster vom Konstruktor von URLPattern
analysiert, in URL-Komponenten zerlegt und jeder Teil des größeren Musters der entsprechenden Komponente zugeordnet. Das bedeutet, dass jede mit Strings erstellte URLPattern
im Grunde genauso dargestellt wird wie eine entsprechende URLPattern
, die mit einem Objekt erstellt wurde. Der Konstruktor für Strings ist nur eine Verknüpfung für diejenigen, die eine weniger ausladende Benutzeroberfläche bevorzugen.
const p = new URLPattern('https://example.com/foo/:image.jpg?*#*');
Wenn Sie Strings zum Erstellen einer URLPattern
verwenden, müssen Sie einige Einschränkungen beachten.
Wenn Sie eine Property weglassen, wenn Sie URLPattern
mit einem Objekt erstellen, entspricht das dem Angeben eines *
-Platzhalters für diese Property. Wenn beim Parsen des vollständigen URL-Strings einer der URL-Komponenten ein Wert fehlt, wird davon ausgegangen, dass die Eigenschaft der Komponente auf ''
festgelegt ist. Das ist nur dann der Fall, wenn die Komponente leer ist.
Wenn Sie Strings verwenden, müssen Sie die Platzhalter explizit angeben, damit sie in der erstellten URLPattern
verwendet werden.
// p1 and p2 are equivalent.
const p1 = new URLPattern('/foo', location.origin);
const p2 = new URLPattern({
protocol: location.protocol,
hostname: location.hostname,
pathname: '/foo',
search: '',
hash: '',
});
// p3 and p4 are equivalent.
const p3 = new URLPattern('/foo?*#*', location.origin);
const p4 = new URLPattern({
protocol: location.protocol,
hostname: location.hostname,
pathname: '/foo',
});
Außerdem ist zu beachten, dass das Parsen eines Stringmusters in seine Komponenten potenziell mehrdeutig ist. Es gibt Zeichen wie :
, die in URLs vorkommen, aber auch eine besondere Bedeutung in der Syntax für die Musterabgleich haben. Um diese Mehrdeutigkeit zu vermeiden, geht der Konstruktor von URLPattern
davon aus, dass alle diese Sonderzeichen Teil eines Musters und nicht Teil der URL sind. Wenn ein mehrdeutiges Zeichen als Teil der URL interpretiert werden soll, muss es mit einem Escapezeichen \` character. For example, the literal URL
about:blankshould be escaped as
'about\:blank'` versehen werden, wenn es als String angegeben wird.
Muster verwenden
Nachdem Sie einen URLPattern
erstellt haben, haben Sie zwei Möglichkeiten, ihn zu verwenden. Die Methoden test()
und exec()
nehmen dieselbe Eingabe an und verwenden denselben Algorithmus, um nach einer Übereinstimmung zu suchen. Sie unterscheiden sich nur durch den Rückgabewert. test()
gibt true
zurück, wenn eine Übereinstimmung mit der angegebenen Eingabe gefunden wird, andernfalls false
.
exec()
gibt detaillierte Informationen zur Übereinstimmung zusammen mit Erfassungsgruppen zurück oder null
, wenn keine Übereinstimmung gefunden wurde. In den folgenden Beispielen wird exec()
verwendet. Sie können aber auch test()
verwenden, wenn Sie nur einen einfachen booleschen Rückgabewert benötigen.
Eine Möglichkeit, die Methoden test()
und exec()
zu verwenden, besteht darin, Strings zu übergeben.
Ähnlich wie beim Konstruktor sollte es sich bei einem einzelnen String, der angegeben wird, um eine vollständige URL handeln, einschließlich des Ursprungs. Wenn zwei Strings angegeben werden, wird der zweite String als baseURL
-Wert behandelt und der erste String wird relativ zu dieser Basis ausgewertet.
const p = new URLPattern({
pathname: '/foo/:image.jpg',
baseURL: 'https://example.com',
});
const result = p.exec('https://example.com/foo/cat.jpg');
// result will contain info about the successful match.
// const result = p.exec('/foo/cat.jpg', 'https://example.com')
// is equivalent, using the baseURL syntax.
const noMatchResult = p.exec('https://example.com/bar');
// noMatchResult will be null.
Alternativ können Sie dieselbe Art von Objekt übergeben, die vom Konstruktor unterstützt wird, mit Properties, die nur auf die Teile der URL festgelegt sind, die abgeglichen werden sollen.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
const result = p.exec({pathname: '/foo/:image.jpg'});
// result will contain info about the successful match.
Wenn Sie exec()
auf eine URLPattern
anwenden, die Wildcards oder Tokens enthält, enthält der Rückgabewert Informationen zu den entsprechenden Werten in der Eingabe-URL. So müssen Sie diese Werte nicht selbst herausfinden.
const p = new URLPattern({
hostname: ':subdomain.example.com',
pathname: '/*/:image.jpg'
});
const result = p.exec('https://imagecdn1.example.com/foo/cat.jpg');
// result.hostname.groups.subdomain will be 'imagecdn1'
// result.pathname.groups[0] will be 'foo', corresponding to *
// result.pathname.groups.image will be 'cat'
Anonymes und benannte Gruppen
Wenn Sie einen URL-String an exec()
übergeben, erhalten Sie einen Wert zurück, der angibt, welche Teile mit allen Gruppen des Musters übereinstimmen.
Der Rückgabewert hat Eigenschaften, die den Komponenten der URLPattern
entsprechen, z. B. pathname
. Wenn eine Gruppe als Teil des pathname
-Teils von URLPattern
definiert wurde, finden Sie die Übereinstimmungen in pathname.groups
des Rückgabewerts. Die Übereinstimmungen werden unterschiedlich dargestellt, je nachdem, ob das entsprechende Muster eine anonyme oder benannte Gruppe war.
Sie können Arrayindizes verwenden, um auf die Werte für eine anonyme Musterübereinstimmung zuzugreifen.
Wenn mehrere anonyme Muster vorhanden sind, steht Index 0
für den übereinstimmenden Wert des Musters links, während 1
und weitere Indexe für nachfolgende Muster verwendet werden.
Wenn Sie benannte Gruppen in einem Muster verwenden, werden die Übereinstimmungen als Properties angezeigt, deren Namen den jeweiligen Gruppennamen entsprechen.
Unicode-Unterstützung und ‑Normalisierung
URLPattern
unterstützt Unicode-Zeichen auf verschiedene Arten.
Benannte Gruppen wie
:café
können Unicode-Zeichen enthalten. Die Regeln für gültige JavaScript-IDs gelten auch für benannte Gruppen.Text in einem Muster wird automatisch gemäß denselben Regeln codiert, die für die URL-Codierung der jeweiligen Komponente verwendet werden. Unicode-Zeichen in
pathname
werden prozentcodiert. Einpathname
-Muster wie/café
wird also automatisch in/caf%C3%A9
normalisiert. Unicode-Zeichen in derhostname
werden automatisch mit Punycode und nicht mit Prozentcodierung codiert.Reguläre Ausdrucksgruppen dürfen nur ASCII-Zeichen enthalten. Die Syntax von regulären Ausdrücken macht es schwierig und unsicher, Unicode-Zeichen in diesen Gruppen automatisch zu codieren. Wenn Sie ein Unicode-Zeichen in einer regulären Ausdrucksgruppe abgleichen möchten, müssen Sie es manuell mit dem Prozentzeichen codieren, z. B.
(caf%C3%A9)
fürcafé
.
Neben der Codierung von Unicode-Zeichen führt URLPattern
auch eine URL-Normalisierung durch. Beispiel: /foo/./bar
in der pathname
-Komponente wird auf die entsprechende /foo/bar
minimiert.
Wenn Sie sich nicht sicher sind, wie ein bestimmtes Eingabemuster normalisiert wurde, können Sie die erstellte URLPattern
-Instanz mit den DevTools Ihres Browsers prüfen.
Zusammenfassung
Die unten eingebettete Glitch-Demo veranschaulicht einen zentralen Anwendungsfall von URLPattern
innerhalb der fetch event handler
eines Service Workers. Dabei werden bestimmte Muster asynchronen Funktionen zugeordnet, die eine Antwort auf Netzwerkanfragen generieren können. Die Konzepte in diesem Beispiel können auch auf andere Routingszenarien angewendet werden, entweder server- oder clientseitig.
Feedback und zukünftige Pläne
Die grundlegenden Funktionen für URLPattern
sind bereits in Chrome und Edge verfügbar. Es sind aber weitere Ergänzungen geplant. Einige Aspekte von URLPattern
befinden sich noch in der Entwicklungsphase und es gibt eine Reihe von offenen Fragen zu bestimmten Verhaltensweisen, die noch optimiert werden können. Wir empfehlen dir, URLPattern
auszuprobieren und uns Feedback über ein GitHub-Problem zu geben.
Unterstützung für Vorlagen
Die path-to-regexp
-Bibliothek bietet eine compile() function
, mit der das Routingverhalten effektiv umgekehrt wird. compile()
nimmt ein Muster und Werte für die Token-Platzhalter an und gibt einen String für einen URL-Pfad zurück, in dem diese Werte eingefügt sind.
Wir hoffen, diese Funktion in Zukunft URLPattern hinzuzufügen, sie ist aber nicht Teil der ersten Version.
Zukünftige Webplattformfunktionen aktivieren
Angenommen, URLPattern
wird ein etablierter Teil der Webplattform, können andere Funktionen, die von Routing oder Musterabgleich profitieren könnten, darauf aufbauen.
Es gibt laufende Diskussionen über die Verwendung von URLPattern
für vorgeschlagene Funktionen wie Musterabgleich im Service Worker-Umfang, PWAs als Dateihandler und vorsorgliches Vorabladen.
Danksagungen
Eine vollständige Liste der Mitwirkenden finden Sie im ursprünglichen Erklärdokument.