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