פורסם: 22 ביולי 2021
ניתוב הוא חלק מרכזי בכל אפליקציית אינטרנט. ניתוב הוא תהליך שבו לוקחים כתובת URL, מחילים עליה התאמה לתבנית או לוגיקה אחרת שספציפית לאפליקציה, ואז בדרך כלל מציגים תוכן אינטרנט על סמך התוצאה. אפשר להטמיע ניתוב בכמה דרכים:
- קוד שרת שממפה נתיבים לקבצים בדיסק
- לוגיקה באפליקציה של דף יחיד שמחכה לשינויים במיקום הנוכחי, ואז יוצרת ומציגה קטע DOM תואם.
אין תקן מוגדר אחד, אבל מפתחי אתרים נוטים להשתמש בתחביר משותף לביטוי תבניות של ניתוב כתובות URL, שדומה מאוד ל-regular expressions, אבל עם כמה תוספות ספציפיות לדומיין, כמו טוקנים להתאמה של פלחי נתיב.
במסגרות פופולריות בצד השרת כמו Express ו-Ruby on Rails נעשה שימוש בתחביר הזה (או בתחביר דומה מאוד), ומפתחי JavaScript יכולים להשתמש במודולים כמו path-to-regexp או regexpparam כדי להוסיף את הלוגיקה הזו לקוד שלהם.
URLPattern
הוא תוספת לפלטפורמת האינטרנט שמבוססת על התשתית שנוצרה
על ידי המסגרות האלה. המטרה שלו היא ליצור סטנדרט לתחביר של תבניות ניתוב, כולל תמיכה בתווים כלליים, בקבוצות של טוקנים עם שמות, בקבוצות של ביטויים רגולריים ובמשנים של קבוצות. URLPattern instances שנוצרו באמצעות התחביר הזה
יכולות לבצע משימות נפוצות של ניתוב, כמו התאמה לכתובות URL מלאות או לכתובת URL
pathname,
ולהחזיר מידע על התאמות של טוקנים וקבוצות.
יתרון נוסף של התאמת כתובות URL ישירות בפלטפורמת האינטרנט הוא שאפשר לשתף תחביר משותף עם ממשקי API אחרים שגם צריכים להתאים לכתובות URL.
תמיכה בדפדפנים ו-polyfills
URLPattern מופעל כברירת מחדל ב-Chrome וב-Edge מגרסה 95 ואילך.
הספרייה
urlpattern-polyfill
מספקת דרך להשתמש בממשק URLPattern בדפדפנים או בסביבות כמו Node שאין להן תמיכה מובנית. אם אתם משתמשים ב-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. אתם יכולים לקרוא את המסמכים שנועדו לפרסום ב-MDN במיקום הנוכחי שלהם ב-GitHub.
תכונות נוספות
התחביר של URLPattern הוא קבוצת-על של מה ש-path-to-regexp תומך בו, כי URLPattern תומך בתכונה לא נפוצה בספריות ניתוב: התאמה של מקורות, כולל תווים כלליים בשמות מארחים. רוב ספריות הניתוב האחרות מתייחסות רק לpathname, ולפעמים לחיפוש או לגיבוב בחלק של כתובת URL. הם אף פעם לא צריכים לבדוק את החלק של המקור בכתובת URL, כי הם משמשים רק לניתוב מאותו מקור באפליקציית אינטרנט עצמאית.
התייחסות למקורות מאפשרת תרחישי שימוש נוספים, כמו ניתוב בקשות חוצות-מקורות בתוך service worker של fetch event handler. אם אתם מנתבים רק כתובות URL מאותו מקור, אתם יכולים להתעלם מהתכונה הנוספת הזו ולהשתמש ב-URLPattern כמו בספריות אחרות.
דוגמאות
בניית התבנית
כדי ליצור URLPattern, מעבירים את ה-constructor שלו כמחרוזות או כאובייקט שהמאפיינים שלו מכילים מידע על התבנית שצריך להתאים לה.
העברת אובייקט מאפשרת לכם לקבוע באופן הכי ברור איזו תבנית תשמש להתאמת כל רכיב של כתובת URL. במצב הכי מפורט, זה יכול להיראות כך:
const p = new URLPattern({
protocol: 'https',
username: '',
password: '',
hostname: 'example.com',
port: '',
pathname: '/foo/:image.jpg',
search: '*',
hash: '*',
});
אם תספקו מחרוזת ריקה למאפיין, תהיה התאמה רק אם החלק המתאים בכתובת ה-URL לא מוגדר. התו הכללי * יתאים לכל ערך בחלק מסוים של כתובת ה-URL.
הקונסטרוקטור מציע כמה קיצורי דרך לשימוש פשוט יותר. השמטה מוחלטת של search ושל hash, או של מאפיינים אחרים, שקולה להגדרתם כתו כללי '*'. אפשר לפשט את הדוגמה כך:
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',
});
כל הדוגמאות האלה מבוססות על ההנחה שהתרחיש לדוגמה שלכם כולל מקורות תואמים. אם אתם רוצים להתאים רק את החלקים האחרים של כתובת ה-URL, לא כולל המקור (כמו במקרים רבים של ניתוב ממקור יחיד), אתם יכולים להשמיט את פרטי המקור לחלוטין ולספק רק שילוב כלשהו של המאפיינים pathname, search ו-hash. כמו קודם, מאפיינים שהושמטו יטופלו כאילו הם הוגדרו לתבנית התו הכללי *.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
במקום להעביר אובייקט ל-constructor, אפשר לספק מחרוזת אחת או שתיים. אם מספקים מחרוזת אחת, היא צריכה לייצג תבנית מלאה של כתובת URL, כולל פרטי התבנית שמשמשים להתאמה למקור. אם מספקים שני מחרוזות, המחרוזת השנייה משמשת כ-baseURL, והמחרוזת הראשונה נחשבת יחסית לבסיס הזה.
לא משנה אם מספקים מחרוזת אחת או שתיים, בנאי URLPattern ינתח את תבנית כתובת ה-URL המלאה, יחלק אותה לרכיבי כתובת URL וימפה כל חלק מהתבנית הגדולה לרכיב המתאים. כלומר, מתחת לפני השטח, כל URLPattern שנוצר באמצעות מחרוזות מיוצג באותו אופן כמו URLPattern מקביל שנוצר באמצעות אובייקט. הבונה של המחרוזות הוא רק קיצור דרך, למי שמעדיף ממשק פחות מפורט.
const p = new URLPattern('https://example.com/foo/:image.jpg?*#*');
כשמשתמשים במחרוזות כדי ליצור URLPattern, יש כמה דברים שחשוב לזכור.
אם לא מציינים מאפיין כשמשתמשים באובייקט כדי ליצור URLPattern, זה שווה ערך לציון תבנית wildcard * עבור המאפיין הזה. כשמנתחים את הדפוס של מחרוזת כתובת ה-URL המלאה, אם חסר ערך לאחד מרכיבי כתובת ה-URL, המערכת מתייחסת לכך כאילו המאפיין של הרכיב הוגדר כ-'', ויהיה התאמה רק אם הרכיב הזה ריק.
כשמשתמשים במחרוזות, צריך לכלול במפורש את התווים הכלליים אם רוצים שהם ישמשו ב-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',
});
חשוב לדעת גם שפירוק של תבנית מחרוזת לרכיבים שלה עלול להיות דו-משמעי. יש תווים, כמו :, שמופיעים בכתובות URL אבל יש להם גם משמעות מיוחדת בתחביר של התאמת תבניות. כדי למנוע את הדו-משמעות הזו, הקונסטרוקטור URLPattern מניח שכל אחד מהתווים המיוחדים האלה הוא חלק מתבנית, ולא חלק מכתובת ה-URL. אם רוצים שתו לא חד-משמעי יפורש כחלק מכתובת ה-URL, צריך להוסיף לפניו את התו \` character. For example, the literal URLabout:blankshould be escaped as'about\:blank'` כשמספקים אותו כמחרוזת.
שימוש בקו פתיחת הנעילה
אחרי שיוצרים URLPattern, יש שתי אפשרויות לשימוש בו. השיטות
test() ו-exec() מקבלות את אותו קלט ומשתמשות באותו אלגוריתם כדי לבדוק אם יש התאמה, וההבדל ביניהן הוא רק בערך ההחזרה. test()
מחזירה true אם יש התאמה לקלט שצוין, ו-false אחרת.
exec() מחזירה מידע מפורט על ההתאמה יחד עם קבוצות לחילוץ, או null אם אין התאמה. בדוגמאות הבאות מוצג שימוש ב-exec(), אבל אפשר להחליף אותו ב-test() בכל אחת מהדוגמאות אם רוצים רק ערך בוליאני שמוחזר.
אחת הדרכים להשתמש בשיטות test() ו-exec() היא להעביר מחרוזות.
בדומה למה שנתמך ב-constructor, אם מספקים מחרוזת אחת, היא צריכה להיות כתובת URL מלאה, כולל המקור. אם מציינים שתי מחרוזות, המחרוזת השנייה נחשבת לערך 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.
לחלופין, אפשר להעביר את אותו סוג של אובייקט שהקונסטרוקטור תומך בו, עם מאפיינים שמוגדרים רק לחלקים של כתובת ה-URL שחשובים להתאמה.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
const result = p.exec({pathname: '/foo/:image.jpg'});
// result will contain info about the successful match.
כשמשתמשים ב-exec() ב-URLPattern שמכיל תווים כלליים או טוקנים, ערך ההחזרה יספק מידע על הערכים התואמים בכתובת ה-URL של הקלט. כך לא תצטרכו לנתח את הערכים האלה בעצמכם.
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'
קבוצות אנונימיות וקבוצות עם שם
כשמעבירים מחרוזת של כתובת URL לפונקציה exec(), מקבלים בחזרה ערך שמציין אילו חלקים תאמו לכל הקבוצות של התבנית.
לערך המוחזר יש מאפיינים שתואמים לרכיבים של URLPattern, כמו pathname. לכן, אם קבוצה הוגדרה כחלק מהקטע pathname של URLPattern, ההתאמות יופיעו ב-pathname.groups של ערך ההחזרה. ההתאמות מוצגות בצורה שונה, בהתאם לסוג הקבוצה שהתבנית המתאימה הייתה שייכת אליה – קבוצה אנונימית או קבוצה עם שם.
אפשר להשתמש באינדקסים של מערכים כדי לגשת לערכים של התאמה אנונימית לתבנית.
אם יש כמה דפוסים אנונימיים, האינדקס 0 מייצג את הערך התואם לדפוס השמאלי ביותר, והאינדקסים 1 ואלה שבהמשך משמשים לדפוסים הבאים.
כשמשתמשים בקבוצות עם שמות בתבנית, ההתאמות מוצגות כמאפיינים שהשמות שלהם תואמים לכל שם קבוצה.
תמיכה ב-Unicode ונורמליזציה
URLPattern תומך בתווי Unicode בכמה דרכים שונות.
קבוצות עם שם, כמו
:café, יכולות להכיל תווי Unicode. הכללים שמשמשים למזהים תקפים של JavaScript חלים על קבוצות עם שם.טקסט בתוך תבנית יקודד אוטומטית לפי אותם כללים שמשמשים לקידוד כתובת URL של הרכיב הספציפי הזה. תווי Unicode בתוך
pathnameיעברו קידוד באחוזים, כך שתבניתpathnameכמו/caféתנורמל באופן אוטומטי ל-/caf%C3%A9. תווי Unicode ב-hostnameמקודדים אוטומטית באמצעות Punycode, ולא באמצעות קידוד באחוזים.קבוצות של ביטויים רגולריים חייבות להכיל רק תווים מסוג ASCII. התחביר של הביטויים הרגולריים מקשה על קידוד אוטומטי של תווים ב-Unicode בקבוצות האלה, וגם הופך את הקידוד ללא בטוח. אם רוצים להתאים תו Unicode בקבוצת ביטויים רגולריים, צריך לבצע קידוד באחוזים באופן ידני, כמו
(caf%C3%A9)כדי להתאים ל-café.
בנוסף לקידוד של תווי Unicode, הפונקציה URLPattern מבצעת גם נורמליזציה של כתובות URL. לדוגמה, /foo/./bar ברכיב pathname מצומצם למקבילה /foo/bar.
אם אתם לא בטוחים איך תבנית קלט מסוימת עברה נרמול, כדאי לבדוק את מופע URLPattern שנוצר באמצעות DevTools של הדפדפן.
סיכום של כל המידע
הדמו של Glitch ממחיש תרחיש שימוש מרכזי ב-URLPattern
בתוך fetch event handler של Service Worker,
מיפוי של תבניות ספציפיות לפונקציות אסינכרוניות שיכולות ליצור תגובה לבקשות רשת. אפשר להחיל את המושגים בדוגמה הזו גם על תרחישי ניתוב אחרים, בצד השרת או בצד הלקוח.
משוב ותוכניות עתידיות
הפונקציונליות הבסיסית של URLPattern זמינה ב-Chrome וב-Edge,
אבל אנחנו מתכננים להוסיף עוד אפשרויות. חלק מההיבטים של URLPattern עדיין בפיתוח, ויש מספר שאלות פתוחות לגבי התנהגויות ספציפיות שעשויות להשתנות. אנחנו ממליצים לנסות את URLPattern ולשלוח משוב באמצעות בעיה ב-GitHub.
תמיכה בתבניות
ספריית path-to-regexp מספקת compile() function שמבטלת את התנהגות הניתוב. הפונקציה compile() מקבלת תבנית וערכים ל-placeholders של אסימונים, ומחזירה מחרוזת של נתיב URL עם הערכים האלה.
אנחנו מקווים להוסיף את זה ל-URLPattern בעתיד, אבל זה לא נכלל בגרסה הראשונית.
הפעלת תכונות עתידיות של פלטפורמת האינטרנט
בהנחה ש-URLPattern יהפוך לחלק מבוסס בפלטפורמת האינטרנט, תכונות אחרות שיכולות להפיק תועלת מניתוב או מהתאמת תבניות יכולות להסתמך עליו כפרימיטיב.
מתנהלים דיונים שוטפים על שימוש ב-URLPattern בתכונות מוצעות כמו התאמת דפוסים של היקף service worker, אפליקציות PWA ככלי לטיפול בקבצים ואחזור מראש ספקולטיבי.
רשימת התודות המלאה מופיעה במסמך ההסבר המקורי.