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 ด้วย

การรองรับเบราว์เซอร์และ Polyfill

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 เนื่องจากมีไว้สําหรับการกำหนดเส้นทางต้นทางเดียวกันภายในเว็บแอปแบบสําเร็จรูปเท่านั้น

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

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

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

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

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

เราหวังว่าจะได้เพิ่ม URL นี้ลงในรูปแบบ URL ในอนาคต แต่ก็ไม่อยู่ภายในขอบเขตของการเผยแพร่ครั้งแรก

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

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

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

ขอขอบคุณ

โปรดดูเอกสารอธิบายต้นฉบับสำหรับรายการรับทราบทั้งหมด