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

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

ที่มา

การกำหนดเส้นทางเป็นกุญแจสำคัญของทุกเว็บแอปพลิเคชัน หัวใจสำคัญของการกำหนดเส้นทางคือ การนำ URL ไปใช้ การใช้การจับคู่รูปแบบ หรือตรรกะเฉพาะแอปอื่นๆ กับ 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 และบางครั้งก็ส่วน search หรือ แฮช ของ URL พวกเขาไม่จำเป็นต้องตรวจสอบส่วนต้นทางของ URL เนื่องจากจะใช้สำหรับการกำหนดเส้นทางต้นทางเดียวกันภายในเว็บแอปในตัวเท่านั้น

การคำนึงถึงต้นทางจะช่วยเปิดประตูสู่กรณีการใช้งานเพิ่มเติม เช่น การกําหนดเส้นทางคําขอแบบข้ามต้นทางภายในตัวแฮนเดิลเหตุการณ์ fetch ของโปรแกรมทำงานของบริการ หากคุณกำหนดเส้นทางเฉพาะ 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 สตริงก็ได้ หากมีการระบุสตริง 1 สตริง สตริงดังกล่าวควรแสดงรูปแบบ URL แบบเต็ม รวมถึงข้อมูลรูปแบบที่ใช้จับคู่กับต้นทาง หากระบุ 2 สตริง ระบบจะใช้สตริงที่ 2 เป็น baseURL และจะถือว่าสตริงแรกสัมพันธ์กับฐานนั้น

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

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

เมื่อใช้สตริงเพื่อสร้าง URLPattern มีข้อควรระวัง 2-3 ข้อที่ควรทราบ

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

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

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

การสนับสนุนสำหรับการกำหนดเทมเพลต

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

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

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

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

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

ข้อความแสดงการยอมรับ

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