URLPattern 提供路徑至網路平台

將常見模式比對用途標準化的方法。

背景

轉送是每個網頁應用程式的關鍵要素。轉送作業的核心是擷取網址、對網址套用一些模式比對或其他應用程式專屬邏輯,然後通常會根據結果顯示網頁內容。轉送作業的實作方式有很多種,例如程式碼有時會在伺服器上執行程式碼來對應磁碟上的檔案路徑,或者是單頁應用程式中的邏輯,以等待變更目前位置並建立要顯示的對應 DOM。

雖然沒有明確的標準,但網頁程式開發人員遵循了通用語法,用來表示與 regular expressions 有許多共用的網址轉送模式,但有一些特定網域附加項目,例如比對路徑區段的權杖。ExpressRuby on Rails 等熱門的伺服器端架構使用這個語法 (或相當接近),且 JavaScript 開發人員可以使用 path-to-regexpregexpparam 等模組,將該邏輯加入自己的程式碼。

URLPattern 是網路平台的新增版本,以這些架構建立的基礎為基礎。它的目標是將轉送模式語法標準化,包括支援萬用字元、已命名權杖群組、規則運算式群組和群組修飾符。使用這個語法建立的 URLPattern 執行個體可以執行常見的轉送工作 (例如比對完整網址或網址 pathname),並傳回權杖與群組相符項目的相關資訊。

直接在網路平台中提供網址比對的另一個好處,是可將通用語法提供給其他 API,而這些 API 也需要與網址進行比對。

瀏覽器支援和 polyfill

根據預設,Chrome 和 Edge 95 以上版本會啟用 URLPattern

urlpattern-polyfill 程式庫提供了在瀏覽器或環境 (例如 Node) 等沒有內建支援的環境中使用 URLPattern 介面的方法。如果您使用 polyfill,請務必使用功能偵測功能,確保只有在目前的環境不支援時,才會載入該功能。否則,您將無法使用 URLPattern 的其中一項主要優點:支援環境不必下載並剖析額外的程式碼就能使用。

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

語法相容性

URLPattern 的指導原則是避免報復。如果您已熟悉 Express 或 Ruby on Rails 中使用的轉送語法,應該不需要學習任何新知識。不過,由於熱門路線程式庫的語法之間有些微差異,因此必須選擇以基本語法做為基礎語法,而 URLPattern 的設計人員則決定使用 path-to-regexp 的模式語法 (但不是其 API 介面)。

path-to-regexp 目前的維護人員密切諮詢後,做出了這項決定。

如要熟悉支援語法的核心,最好的方法就是請參閱 path-to-regexp說明文件。您可以前往 GitHub 目前的首頁,閱讀適合在 MDN 上發布的說明文件。

其他功能

URLPattern 的語法是 path-to-regexp 支援的超集,因為 URLPattern 支援在路徑程式庫之間使用罕見的功能:比對來源,包括主機名稱中的萬用字元。大多數其他轉送程式庫只會處理「路徑名稱」,有時也會處理網址的搜尋雜湊部分。這些引數只會用於獨立網頁應用程式中的相同來源轉送,因此不必檢查網址的來源部分。

將來源納入考量可開啟更多用途,例如在服務工作站fetch 事件處理常式內轉送跨來源要求。如果您只會轉送相同來源網址,可以有效忽略這項額外功能,並像其他程式庫一樣使用 URLPattern

示例

建立模式

如要建立 URLPattern,請傳遞其建構函式字串,或是屬性包含要比對模式資訊的物件。

傳遞物件可讓您以最明確的方式,控管比對每個網址元件時要使用的模式。簡單來說,看起來可能像

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

只有在未設定網址對應的部分時,系統才會比對為屬性提供空白字串。萬用字元 * 會比對網址指定部分的任何值。

建構函式提供幾種方便使用的捷徑。完全省略 searchhash 或任何其他屬性,相當於將其設定為 '*' 萬用字元。上述範例也可以簡化為

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

如要做為額外捷徑,您可以在單一屬性 baseURL 中提供所有起點相關資訊,進而

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

所有範例均假設您的用途涉及比對來源。如果只想比對網址的其他部分,並排除來源 (許多「傳統」單一來源轉送情境的情況),則可以完全省略起點資訊,只提供 pathnamesearchhash 屬性的某些組合。如先前所述,系統會將省略的屬性視為其設為 * 萬用字元模式。

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

除了將物件傳入建構函式之外,您也可以提供一或兩個字串。如果提供一個字串,該字串應代表完整的網址模式,包括用於比對來源的模式資訊。如果您提供兩個字串,系統會將第二個字串做為 baseURL 使用,然後將第一個字串視為相對於該基數。

無論提供一個字串,URLPattern 建構函式都會剖析完整網址模式、將其分割為網址元件,並將大型模式的各部分對應至對應的元件。這表示在背景中,每個透過字串建立的 URLPattern 最終都會表示與使用物件建立的對等 URLPattern 相同。字串建構函式只是捷徑,適合偏好較簡介介面的使用者。

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

使用字串建立 URLPattern 時,請注意以下幾點。

使用物件建構 URLPattern 時,若保留該屬性,相當於為該屬性提供 * 萬用字元。剖析完整的網址字串模式時,如果其中一個網址元件缺少值,系統會將其視為元件的屬性設為 '' 時,只會比對該元件為空白時。

使用字串時,如果您想在建構的 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',
});

您也應瞭解,將字串模式剖析為其元件可能會有模稜兩可的情況。網址中有 : 等字元,但在模式比對語法中也有特殊意義。為避免這種混淆,URLPattern 建構函式會假設這些特殊字元都是模式的一部分,而非網址的一部分。如果您想將模稜兩可的字元解讀為網址的一部分,請務必以 \` character. For example, the literal URLabout:blankshould be escaped as'about\:blank'` 來逸出該字元。

使用模式

建構 URLPattern 後,有兩種使用方法。test()exec() 方法都採用相同的輸入內容,且都會使用相同的演算法檢查是否相符,只有回傳的值有所不同。test() 會在有相符項目的輸入時傳回 true,否則會傳回 falseexec() 會傳回相符項目的詳細資訊與擷取群組;如果沒有任何相符項目,則會傳回 null。以下示例示範如何使用 exec(),但如果您只想使用簡單的布林值,也可以將 test() 換成任意布林值。

使用 test()exec() 方法的其中一種方法是傳入字串。與建構函式支援的功能類似,如果提供單一字串,則應為包含來源的完整網址。如果提供兩個字串,系統會將第二個字串視為 baseURL 值,並評估第一個字串的相對值。

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.

或者,您也可以傳遞建構函式支援的相同物件類型,並將屬性設為您重視比對的網址部分。

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

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

在含有萬用字元或符記的 URLPattern 上使用 exec() 時,回傳值會提供關於輸入網址中對應值的資訊。這樣您就不必自行剖析這些值。

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'

匿名和已命名的群組

將網址字串傳送至 exec() 後,您就會收到一個值,指出哪些部分與模式群組的所有群組相符。

回傳值具有與 URLPattern 元件相對應的屬性,例如 pathname。因此,如果群組定義為 URLPatternpathname 部分的一部分,則可在回傳值的 pathname.groups 中找到相符項目。比對相符項目的格式取決於對應的模式是匿名群組或已命名群組。

您可以使用陣列索引存取匿名模式比對的值。如果有多個匿名模式,索引 0 會代表最左邊的相符值,加上 1 和進一步的索引用於後續模式。

在模式中使用已命名群組時,相符項目會以屬性形式公開,且名稱對應每個群組名稱。

萬國碼 (Unicode) 支援和正規化

URLPattern 能以幾種不同方式支援萬國碼 (Unicode) 字元。

  • 具名群組 (例如 :café) 可以包含萬國碼 (Unicode) 字元。用於有效 JavaScript ID 的規則適用於已命名群組。

  • 模式中的文字將根據特定元件的網址編碼使用相同規則自動進行編碼。pathname 中的萬國碼 (Unicode) 字元將進行百分比編碼,因此 /cafépathname 模式會自動標準化為 /caf%C3%A9hostname 中的萬國碼 (Unicode) 字元會自動使用 Punycode 編碼,而非百分比編碼。

  • 規則運算式群組只能包含 ASCII 字元。規則運算式語法會導致系統難以自動為這些群組中的 Unicode 字元編碼,也較不安全。如要在規則運算式群組中比對萬國碼 (Unicode) 字元,您必須手動對其進行百分比編碼,例如使用 (caf%C3%A9) 來比對 café

除了將 Unicode 字元編碼外,URLPattern 還會執行網址正規化。舉例來說,pathname 元件中的 /foo/./bar 會收合為對等的 /foo/bar

如對指定輸入模式如何正規化有任何疑問,請使用瀏覽器的DevTools檢查建構的 URLPattern 執行個體。

平台比一比

下方嵌入的 Glitch 示範示範了服務工作站 fetch event handlerURLPattern 的核心用途,將特定模式對應至可產生網路要求回應的非同步函式。此範例中的概念也適用於其他轉送情境,伺服器端或用戶端。

意見回饋和未來計畫

雖然 URLPattern 的基本功能已成為 Chrome 和 Edge 的功能,但還有額外功能。URLPattern 的某些部分仍在開發中,有一些關於特定行為的開放式問題仍待修正。建議您試用 URLPattern,並透過 GitHub 問題提供意見回饋。

支援範本

path-to-regexp 程式庫提供可有效反轉轉送行為的 compile() functioncompile() 會採用模式預留位置的模式和值,並傳回網址路徑的字串,其中包含替換後的值。

我們希望日後能將此項目加入 URLPattern,但這不在初始版本的範圍內。

啟用日後的網路平台功能

假設 URLPattern 已成為網路平台的既有部分,其他可能受益於轉送或模式比對的功能,會以原始形式為基礎進行建構。

目前已持續討論如何將 URLPattern 用於提議的功能,例如:服務工作站範圍模式比對PWA 做為檔案處理常式,以及推測預先擷取

特別銘謝

如需查看特別銘謝名單,請參閱原始說明文件