URLPattern udostępnia routing na platformę internetową

Podejście do standaryzacji typowych przypadków użycia dopasowania do wzorca.

Wprowadzenie

Routing to kluczowy element każdej aplikacji internetowej. Zasadniczo routing obejmuje przechwytywanie adresu URL, zastosowanie do niego dopasowania do wzorca lub innej logiki związanej z aplikacją, a następnie zwykle wyświetlanie treści internetowych na podstawie wyniku. Routing można wdrożyć na różne sposoby: czasami działa na serwerze jako kod, który mapuje ścieżkę do plików na dysku, lub loguje w aplikacji jednostronicowej, która czeka na zmiany w bieżącej lokalizacji i tworzy odpowiedni fragment DOM do wyświetlenia.

Chociaż nie ma jednego uniwersalnego standardu, deweloperzy stron internetowych preferują wspólną składnię do wyrażania wzorców routingu adresów URL, które mają wiele wspólnego z metodą regular expressions, ale z pewnymi dodatkami specyficznymi dla danej domeny, takimi jak tokeny do dopasowywania segmentów ścieżek. Z tej składni (lub bardzo zbliżonej rzeczy) korzystają popularne platformy po stronie serwera, np. Express czy Ruby on Rails, a programiści JavaScriptu mogą dodawać tę funkcję do swojego kodu za pomocą modułów takich jak path-to-regexp czy regexpparam.

URLPattern to dodatek do platformy internetowej, która opiera się na podstawach tworzonych przez te platformy. Jego celem jest ujednolicenie składni wzorca routingu, w tym obsługę symboli wieloznacznych, nazwanych grup tokenów, grup wyrażeń regularnych i modyfikatorów grup. Instancje URLPattern utworzone z tą składnią mogą wykonywać typowe zadania routingu, takie jak dopasowywanie do pełnych adresów URL lub adresów URL pathname, oraz zwracanie informacji o dopasowaniach tokena i grupy.

Inną zaletą dopasowywania adresów URL bezpośrednio na platformie internetowej jest to, że wspólną składnię można następnie udostępniać innym interfejsom API, które również muszą pasować do adresów URL.

Obsługa przeglądarek i kod polyfill

Funkcja URLPattern jest domyślnie włączona w Chrome i Edge w wersji 95 i nowszych.

Biblioteka urlpattern-polyfill umożliwia korzystanie z interfejsu URLPattern w przeglądarkach lub środowiskach takich jak Węzeł, które nie mają wbudowanej obsługi. Jeśli korzystasz z kodu polyfill, włącz wykrywanie funkcji, by mieć pewność, że wczytujesz je tylko wtedy, gdy w bieżącym środowisku nie działa. W przeciwnym razie stracisz jedną z głównych zalet URLPattern: to, że środowiska pomocy nie muszą pobierać ani analizować dodatkowego kodu, aby z niego korzystać.

if (!(globalThis && 'URLPattern' in globalThis)) {
  // URLPattern is not available, so the polyfill is needed.
}

Zgodność składni

Filozofia firmy URLPattern polega na unikaniu zmian w poszczególnych usługach. Jeśli znasz już składnię routingu używaną w językach Express lub Ruby on Rails, nie musisz uczyć się niczego nowego. Jednak ze względu na niewielkie rozbieżności między składnikami w popularnych bibliotekach routingu trzeba było wybrać coś jako składnię podstawową, a projektanci URLPattern postanowił użyć składni wzorca z path-to-regexp (ale nie jego powierzchni interfejsu API) jako punktu wyjścia.

Podjęliśmy tę decyzję po szczegółowych konsultacjach z obecnym opiekunem domeny path-to-regexp.

Najlepszym sposobem, aby zapoznać się z podstawą obsługiwanej składni, jest zapoznanie się z dokumentacją path-to-regexp. Możesz przeczytać dokumentację przeznaczoną do publikacji w MDN na jej stronie głównej na GitHubie.

Dodatkowe funkcje

Składnia URLPattern jest nadzbiorem obsługiwanych funkcji path-to-regexp, ponieważ URLPattern obsługuje nietypową funkcję spośród bibliotek routingu: dopasowywanie origins, w tym symbole wieloznaczne w nazwach hostów. Większość innych bibliotek routingu obsługuje tylko nazwę ścieżki, a czasami część adresu URL związaną z wyszukiwaniem lub szyfrowaniem. Nigdy nie muszą sprawdzać źródła adresu URL, ponieważ są używane tylko do routingu z tej samej domeny w samodzielnie aplikacji internetowej.

Uwzględnienie źródeł otwiera możliwość zastosowania dodatkowych przypadków użycia, takich jak kierowanie żądań z innych domen w ramach modułu obsługi zdarzeń fetch w skrypcie service worker. Jeśli kierujesz tylko adresy URL z tej samej domeny, możesz zignorować tę dodatkową funkcję i używać funkcji URLPattern tak jak inne biblioteki.

Przykłady

Budowanie wzoru

Aby utworzyć obiekt URLPattern, przekaż jego konstruktor albo ciągi tekstowe lub obiekt, którego właściwości zawierają informacje o wzorcu, do którego mają być dopasowywane.

Przekazywanie obiektu daje najbardziej wyraźną kontrolę nad wzorcem używanym do dopasowywania poszczególnych komponentów adresu URL. W szczególności może to wyglądać tak:

const p = new URLPattern({
  protocol: 'https',
  username: '',
  password: '',
  hostname: 'example.com',
  port: '',
  pathname: '/foo/:image.jpg',
  search: '*',
  hash: '*',
});

Podanie pustego ciągu w przypadku danej usługi będzie dopasowywane tylko wtedy, gdy nie ma odpowiadającej mu części adresu URL. Symbol wieloznaczny * będzie pasować do dowolnej wartości w przypadku danej części adresu URL.

Konstruktor udostępnia kilka skrótów, które ułatwiają korzystanie z nich. Całkowite pominięcie właściwości search, hash lub innych jest równoznaczne z ustawieniem ich symbolu wieloznacznego '*'. Powyższy przykład można uprościć do

const p = new URLPattern({
  protocol: 'https',
  username: '',
  password: '',
  hostname: 'example.com',
  port: '',
  pathname: '/foo/:image.jpg',
});

Dodatkowym skrótem jest możliwość zebrania wszystkich informacji o źródle w jednej usłudze (baseURL), prowadzącej do

const p = new URLPattern({
  pathname: '/foo/:image.jpg',
  baseURL: 'https://example.com',
});

We wszystkich tych przykładach założono, że Twój przypadek użycia obejmuje dopasowywanie źródeł. Jeśli chcesz dopasowywać tylko do innych części adresu URL, z wyłączeniem źródła (co ma miejsce w wielu „tradycyjnych” scenariuszach routingu z jednym źródłem), możesz całkowicie pominąć informacje o źródle i podać kombinację właściwości pathname, search oraz hash. Tak jak wcześniej, pominięte właściwości będą traktowane tak, jakby były ustawione na wzór z symbolem wieloznacznym *.

const p = new URLPattern({pathname: '/foo/:image.jpg'});

Zamiast przekazywać obiekt do konstruktora, możesz podać jeden lub dwa ciągi. Jeśli podasz jeden ciąg znaków, powinien on reprezentować pełny wzorzec adresu URL łącznie z informacjami o wzorcu używanymi do dopasowania źródła. Jeśli podasz 2 ciągi, drugi zostanie użyty jako baseURL, a pierwszy będzie traktowany jako powiązany z tą podstawą.

Niezależnie od tego, czy podasz 1 czy 2 ciągi znaków, konstruktor URLPattern przeanalizuje pełny wzorzec adresu URL, podzieli go na komponenty adresu URL i zmapuje każdy fragment większego wzorca na odpowiedni komponent. Oznacza to, że każdy element URLPattern utworzony za pomocą ciągów znaków będzie reprezentowany tak samo jak odpowiednik URLPattern utworzony za pomocą obiektu. Konstruktor ciągów tekstowych to tylko skrót dla osób, które wolą korzystać z mniej szczegółowego interfejsu.

const p = new URLPattern('https://example.com/foo/:image.jpg?*#*');

Jeśli tworzysz URLPattern z użyciem ciągów tekstowych, musisz pamiętać o kilku kwestiach.

Nieuwzględnienie właściwości podczas korzystania z obiektu do utworzenia URLPattern jest równoważne z umieszczeniem w niej symbolu wieloznacznego *. Jeśli podczas analizy wzorca ciągu znaków pełnego adresu URL brakuje wartości w jednym z komponentów adresu URL, jest ono traktowane tak, jakby właściwość komponentu była ustawiona na '', co będzie pasować tylko wtedy, gdy komponent będzie pusty.

Przy korzystaniu z ciągów znaków musisz jawnie uwzględnić symbole wieloznaczne, jeśli chcesz, aby były używane w zbudowanym obiekcie URLPattern.

// 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',
});

Pamiętaj też, że analizowanie wzorca ciągu znaków na jego komponenty może być niejednoznaczne. W adresach URL występują znaki takie jak :, które mają też szczególne znaczenie w składni dopasowania do wzorca. Aby uniknąć tego dwuznaczności, konstruktor URLPattern zakłada, że którykolwiek z tych znaków specjalnych jest częścią wzorca, a nie adresu URL. Jeśli niejednoznaczny znak ma być interpretowany jako część adresu URL, pamiętaj, aby zastąpić go ciągiem znaków \` character. For example, the literal URLabout:blankshould be escaped as„about:blank” w postaci ciągu znaków.

Korzystanie ze wzoru

Po utworzeniu elementu URLPattern możesz go użyć na 2 sposoby. Metody test() i exec() używają tych samych danych wejściowych i używają tego samego algorytmu do sprawdzania dopasowania, ale różnią się tylko wartością zwracaną. test() zwraca wartość true, jeśli dane wejściowe są dopasowanie. W przeciwnym razie zwraca wartość false. Funkcja exec() zwraca szczegółowe informacje o dopasowaniu razem z grupami przechwytywania lub null, jeśli nie uda się dopasować. Poniższe przykłady pokazują, jak używać funkcji exec(). Jeśli jednak chcesz uzyskać tylko prostą wartość logiczną, możesz zamienić nazwę test() na dowolny z nich.

Jednym ze sposobów korzystania z metod test() i exec() jest przekazanie ciągów tekstowych. Podobnie jak w przypadku konstruktora, jeśli podany jest pojedynczy ciąg, powinien to być pełny adres URL z pierwotnym źródłem. Jeśli podasz 2 ciągi, drugi będzie traktowany jako wartość baseURL, a pierwszy będzie oceniany jako w odniesieniu do tej podstawy.

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.

Możesz też przekazać ten sam rodzaj obiektu, który obsługuje konstruktor, z właściwościami ustawionymi tylko na te części adresu URL, które są istotne dla dopasowania.

const p = new URLPattern({pathname: '/foo/:image.jpg'});

const result = p.exec({pathname: '/foo/:image.jpg'});
// result will contain info about the successful match.

Gdy używasz exec() w obiekcie URLPattern, który zawiera symbole wieloznaczne lub tokeny, zwracana wartość informuje o tym, jakie wartości znajdowały się w wejściowym adresie URL. Dzięki temu nie musisz analizować tych wartości samodzielnie.

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'

grupy anonimowe i nazwane;

Gdy przekażesz ciąg adresu URL do funkcji exec(), otrzymasz wartość wskazującą, które części pasują do wszystkich grup wzorca.

Zwracana wartość ma właściwości odpowiadające komponentom obiektu URLPattern, np. pathname. Jeśli więc grupa została zdefiniowana jako część pathname parametru URLPattern, dopasowania można znaleźć w kolumnie pathname.groups wartości zwracanej. Dopasowania są przedstawiane w różny sposób w zależności od tego, czy dany wzorzec był grupą anonimowy czy nazwaną.

Za pomocą indeksów tablic możesz uzyskać dostęp do wartości dla anonimowego dopasowania do wzorca. Jeśli występuje wiele wzorców anonimowych, indeks 0 będzie reprezentował wartość odpowiadającą identyfikatorowi po lewej stronie, z wartością 1, a następnymi indeksami używanymi w kolejnych wzorach.

Gdy użyjesz grup nazwanych we wzorcu, dopasowania będą widoczne jako właściwości, których nazwy odpowiadają nazwom grup.

obsługa i normalizacja Unicode;

URLPattern obsługuje znaki Unicode na kilka różnych sposobów.

  • Grupy nazwane, np. :café, mogą zawierać znaki Unicode. Reguły używane do prawidłowych identyfikatorów JavaScript mają zastosowanie do grup nazwanych.

  • Tekst we wzorcu będzie automatycznie kodowany zgodnie z regułami używanymi przy kodowaniu adresów URL w przypadku danego komponentu. Znaki Unicode w pathname będą zakodowane za pomocą procentów, więc wzorzec pathname, taki jak /café, jest automatycznie znormalizowany do /caf%C3%A9. Znaki Unicode w elemencie hostname są kodowane automatycznie za pomocą Punycode, a nie w postaci kodowania procentowego.

  • Grupy wyrażeń regularnych mogą zawierać tylko znaki ASCII. Składnia wyrażeń regularnych sprawia, że automatyczne kodowanie znaków Unicode w takich grupach jest trudne i niebezpieczne. Jeśli chcesz dopasować znak Unicode w grupie wyrażeń regularnych, musisz zakodować go ręcznie procentowo, np. (caf%C3%A9), aby dopasować café.

Oprócz kodowania znaków Unicode URLPattern wykonuje też normalizację adresów URL. Na przykład pole /foo/./bar w komponencie pathname jest zwinięte do odpowiadającego mu elementu /foo/bar.

W razie wątpliwości co do tego, jak dany wzorzec danych wejściowych został znormalizowany, sprawdź skonstruowaną instancję URLPattern za pomocą DevTools w przeglądarce.

Podsumowanie

Wbudowana poniżej demonstracja Glitch ilustruje podstawowy przypadek użycia funkcji URLPattern w obrębie fetch event handler skryptu service worker, mapując określone wzorce na funkcje asynchroniczne, które mogą generować odpowiedź na żądania sieciowe. Pojęcia z tego przykładu można też zastosować do innych scenariuszy routingu po stronie serwera lub klienta.

Opinie i przyszłe plany

Podstawowe funkcje URLPattern są dostępne w Chrome i Edge, ale planujemy dodawać kolejne. Niektóre aspekty funkcji URLPattern nadal są opracowywane. Pojawia się też wiele otwartych pytań dotyczących konkretnych zachowań, które można jeszcze dopracować. Zachęcamy do wypróbowania usługi URLPattern i przekazania opinii na jej temat za pomocą problemu na GitHubie.

Obsługa szablonów

Biblioteka path-to-regexp udostępnia obiekt compile() function, który skutecznie odwraca działanie routingu. compile() pobiera wzorzec i wartości obiektów zastępczych tokenów i zwraca ciąg ścieżki adresu URL, w którym wartości te są zastąpione.

Mamy nadzieję w przyszłości dodać ten parametr do wzorca URLPattern, ale nie jest on uwzględniony w pierwszej wersji.

Włączenie przyszłych funkcji platformy internetowej

Zakładając, że URLPattern stanie się uznaną częścią platformy internetowej, inne funkcje, które mogą skorzystać z routingu lub dopasowywania wzorców, mogą być oparte na nim jako element podstawowy.

Trwają dyskusje na temat używania URLPattern w proponowanych funkcjach, takich jak dopasowywanie wzorców zakresu skryptu service worker, PWA jako moduły obsługi plików i spekulacyjne pobieranie z wyprzedzeniem.

Podziękowania

Pełną listę podziękowań znajdziesz w pierwotnym dokumencie wyjaśniającym.