URLPattern นำการกำหนดเส้นทางไปยังแพลตฟอร์มเว็บ

แนวทางในการทำให้ Use Case การจับคู่รูปแบบทั่วไปเป็นมาตรฐาน

ข้อมูลเบื้องต้น

การกำหนดเส้นทางเป็นส่วนสําคัญของเว็บแอปพลิเคชันทุกรายการ หัวใจสำคัญของการกำหนดเส้นทางคือการนํา URL ไปใช้กับการทำงานจับคู่รูปแบบหรือตรรกะอื่นๆ เฉพาะแอป แล้วแสดงเนื้อหาเว็บตามผลลัพธ์ที่ได้ การกำหนดเส้นทางอาจนำไปใช้ได้หลายวิธี เช่น บางครั้งเป็นโค้ดที่ทำงานบนเซิร์ฟเวอร์ซึ่งแมปเส้นทางไปยังไฟล์บนดิสก์ หรือตรรกะในแอปแบบหน้าเดียวที่รอการเปลี่ยนแปลงตำแหน่งปัจจุบันและสร้าง DOM ที่เกี่ยวข้องเพื่อแสดง

แม้ว่าจะไม่มีมาตรฐานที่ชัดเจน แต่นักพัฒนาเว็บก็หันมาใช้ไวยากรณ์ทั่วไปในการเขียนรูปแบบการกำหนดเส้นทาง URL ซึ่งคล้ายกับ regular expressions มาก แต่มีการเพิ่มบางอย่างที่เจาะจงโดเมน เช่น โทเค็นสำหรับการจับคู่ส่วนของเส้นทาง เฟรมเวิร์กฝั่งเซิร์ฟเวอร์ยอดนิยมอย่าง Express และ Ruby on Rails ใช้ไวยากรณ์นี้ (หรือไวยากรณ์ที่คล้ายกันมาก) และนักพัฒนา JavaScript สามารถใช้โมดูลอย่าง path-to-regexp หรือ regexpparam เพื่อเพิ่มตรรกะนั้นลงในโค้ดของตนเอง

URLPattern เป็นแพลตฟอร์มเว็บที่สร้างขึ้นจากรากฐานของเฟรมเวิร์กเหล่านี้ โดยมีเป้าหมายเพื่อกำหนดรูปแบบไวยากรณ์ของรูปแบบการกำหนดเส้นทางให้เป็นมาตรฐาน ซึ่งรวมถึงการรองรับไวลด์การ์ด กลุ่มโทเค็นที่มีชื่อ กลุ่มนิพจน์ทั่วไป และตัวแก้ไขกลุ่ม อินสแตนซ์ URLPattern ที่สร้างขึ้นด้วยไวยากรณ์นี้สามารถทํางานทั่วไปในการกําหนดเส้นทาง เช่น การจับคู่กับ URL แบบเต็มหรือ URL pathname และแสดงผลข้อมูลเกี่ยวกับการจับคู่โทเค็นและกลุ่ม

ข้อดีอีกประการของการกำหนดการจับคู่ URL ในแพลตฟอร์มเว็บโดยตรงคือคุณสามารถแชร์ไวยากรณ์ทั่วไปกับ API อื่นๆ ที่ต้องจับคู่กับ URL ด้วย

การรองรับเบราว์เซอร์และโพลีฟีล

URLPattern จะเปิดใช้โดยค่าเริ่มต้นใน Chrome และ Edge เวอร์ชัน 95 ขึ้นไป

ไลบรารี urlpattern-polyfill มีวิธีใช้อินเทอร์เฟซ URLPattern ในเบราว์เซอร์หรือสภาพแวดล้อมอย่าง Node ซึ่งไม่มีการสนับสนุนในตัว หากใช้ polyfill โปรดตรวจสอบว่าคุณใช้การตรวจหาฟีเจอร์เพื่อให้แน่ใจว่าคุณโหลด 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 เนื่องจากมีไว้สําหรับการกำหนดเส้นทางต้นทางเดียวกันภายในเว็บแอปแบบสําเร็จรูปเท่านั้น

การพิจารณาต้นทางจะเปิดโอกาสให้ใช้กรณีการใช้งานเพิ่มเติม เช่น การกำหนดเส้นทางคำขอข้ามต้นทางภายในตัวแฮนเดิลเหตุการณ์ของ fetchService Worker หากกําลังกําหนดเส้นทาง URL ต้นทางเดียวกันเท่านั้น คุณก็สามารถละเว้นฟีเจอร์เพิ่มเติมนี้และใช้ URLPattern ได้เช่นเดียวกับไลบรารีอื่นๆ

ตัวอย่าง

การสร้างรูปแบบ

หากต้องการสร้าง URLPattern ให้ส่งคอนสตรคเตอร์ของสตริงหรือออบเจ็กต์ที่มีพร็อพเพอร์ตี้ซึ่งมีข้อมูลเกี่ยวกับรูปแบบที่จะจับคู่

การส่งผ่านออบเจ็กต์ช่วยให้คุณควบคุมได้อย่างชัดเจนที่สุดว่าจะให้ใช้รูปแบบใดในการจับคู่องค์ประกอบ 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',
});

ตัวอย่างทั้งหมดนี้ถือว่า Use Case ของคุณเกี่ยวข้องกับต้นทางที่ตรงกัน หากสนใจเฉพาะการจับคู่กับส่วนอื่นๆ ของ URL โดยไม่รวมต้นทาง (เช่นเดียวกับในสถานการณ์การกำหนดเส้นทางแบบ "ดั้งเดิม" หลายสถานการณ์ที่มีต้นทางเดียว) คุณก็ละเว้นข้อมูลต้นทางได้ทั้งหมด แล้วระบุเฉพาะการผสมผสานของพร็อพเพอร์ตี้ pathname, search และ hash เช่นเดียวกับก่อนหน้านี้ ระบบจะถือว่าพร็อพเพอร์ตี้ที่ละเว้นไว้เป็นพร็อพเพอร์ตี้ที่มีรูปแบบไวลด์การ์ด *

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

คุณสามารถระบุสตริงได้ 1 หรือ 2 รายการแทนการส่งออบเจ็กต์ไปยังคอนสตร็กเตอร์ หากระบุสตริงเดียว สตริงดังกล่าวควรเป็นรูปแบบ URL แบบเต็ม รวมถึงข้อมูลรูปแบบที่ใช้จับคู่กับต้นทาง หากคุณระบุสตริง 2 รายการ ระบบจะใช้สตริงที่ 2 เป็น baseURL และพิจารณาสตริงแรกเทียบกับฐานนั้น

ไม่ว่าจะระบุสตริง 1 รายการหรือ 2 รายการ ตัวสร้าง URLPattern จะแยกวิเคราะห์รูปแบบ URL แบบเต็ม โดยแบ่งออกเป็นคอมโพเนนต์ URL และแมปแต่ละส่วนของรูปแบบที่ใหญ่ขึ้นกับคอมโพเนนต์ที่เกี่ยวข้อง ซึ่งหมายความว่า URLPattern แต่ละรายการที่สร้างด้วยสตริงจะแสดงผลเหมือนกันกับ URLPattern ที่เทียบเท่าซึ่งสร้างด้วยออบเจ็กต์ ตัวสร้างสตริงเป็นเพียงทางลัดสำหรับผู้ที่ต้องการอินเทอร์เฟซที่กระชับ

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

สิ่งที่ควรคำนึงถึงเมื่อใช้สตริงเพื่อสร้าง URLPattern

การไม่ระบุพร็อพเพอร์ตี้เมื่อใช้ออบเจ็กต์เพื่อสร้าง URLPattern จะเทียบเท่ากับการให้ไวลด์การ์ด * สําหรับพร็อพเพอร์ตี้นั้น เมื่อระบบแยกวิเคราะห์รูปแบบสตริง 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 แล้ว คุณมี 2 ตัวเลือกในการใช้งาน ทั้ง 2 วิธีใช้อินพุตเดียวกันและใช้อัลกอริทึมเดียวกันในการตรวจสอบการจับคู่ และแตกต่างกันตรงที่ผลลัพธ์เท่านั้นtest()exec() test() จะแสดงผล true เมื่ออินพุตที่ระบุตรงกันและแสดงผล false ในกรณีอื่นๆ exec() จะแสดงข้อมูลโดยละเอียดเกี่ยวกับการจับคู่พร้อมกับแคปเจอร์กรุ๊ป หรือ null หากไม่พบรายการที่ตรงกัน ตัวอย่างต่อไปนี้แสดงการใช้ exec() แต่คุณอาจแทนที่ test() กับตัวอย่างใดก็ได้หากต้องการค่าผลลัพธ์บูลีนธรรมดาเท่านั้น

วิธีหนึ่งในการใช้เมธอด test() และ exec() คือการส่งสตริง เช่นเดียวกับที่ตัวสร้างรองรับ หากระบุสตริงเดียว สตริงดังกล่าวควรเป็น URL แบบเต็ม ซึ่งรวมถึงต้นทาง หากระบุสตริง 2 รายการ ระบบจะถือว่าสตริงที่ 2 เป็นค่า 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 ที่ฝังไว้ด้านล่างแสดง Use Case หลักของ URLPattern ภายในfetch event handler ของ Service Worker โดยแมปรูปแบบที่เฉพาะเจาะจงกับฟังก์ชันแบบแอสซิงโครนัสที่อาจสร้างการตอบกลับคำขอเครือข่าย แนวคิดในตัวอย่างนี้สามารถใช้กับสถานการณ์การกำหนดเส้นทางอื่นๆ ได้ด้วย ไม่ว่าจะเป็นฝั่งเซิร์ฟเวอร์หรือฝั่งไคลเอ็นต์

ความคิดเห็นและแผนในอนาคต

แม้ว่าฟังก์ชันพื้นฐานของ URLPattern จะพร้อมใช้งานใน Chrome และ Edge แล้ว แต่เรายังมีแผนที่จะเพิ่มฟีเจอร์อื่นๆ URLPattern บางแง่มุมยังอยู่ระหว่างการพัฒนา และยังมีคำถามที่ยังไม่ได้รับการตอบอยู่หลายข้อเกี่ยวกับลักษณะการทำงานบางอย่างที่อาจยังต้องปรับแต่ง เราขอแนะนำให้คุณลองใช้ URLPattern และแสดงความคิดเห็นผ่านปัญหาใน GitHub

การรองรับเทมเพลต

ไลบรารี path-to-regexp มี compile() function ที่เปลี่ยนลักษณะการกําหนดเส้นทางได้อย่างมีประสิทธิภาพ compile() จะรับรูปแบบและค่าสำหรับตัวยึดตําแหน่งโทเค็น และแสดงผลสตริงสําหรับเส้นทาง URL ที่มีค่าเหล่านั้นแทนที่

เราหวังว่าจะเพิ่มรายการนี้ลงใน URLPattern ในอนาคต แต่การดำเนินการนี้ไม่อยู่ในขอบเขตของรุ่นแรก

การเปิดใช้ฟีเจอร์แพลตฟอร์มเว็บในอนาคต

สมมติว่า URLPattern กลายเป็นส่วนสำคัญของแพลตฟอร์มเว็บ ฟีเจอร์อื่นๆ ที่อาจได้ประโยชน์จากการกําหนดเส้นทางหรือการจับคู่รูปแบบจะสร้างขึ้นจาก URLPattern เป็นหลัก

เรากำลังหารือกันอย่างต่อเนื่องเกี่ยวกับการใช้ URLPattern สำหรับฟีเจอร์ที่เสนอ เช่น การจับคู่รูปแบบขอบเขต Service Worker, PWA ในฐานะตัวแฮนเดิลไฟล์ และการคาดการณ์การโหลดล่วงหน้า

ขอขอบคุณ

ดูรายการการขอบคุณทั้งหมดได้ในเอกสารอธิบายฉบับต้นฉบับ