เพิ่มประสิทธิภาพในการบีบอัดด้วยพจนานุกรมที่แชร์

การบีบอัดข้อมูลเป็นเทคนิคการเพิ่มประสิทธิภาพที่ผ่านการทดสอบมาอย่างยาวนานซึ่งจะลดขนาดทรัพยากรหน้าเว็บที่มีสิทธิ์ ในช่วงหนึ่ง แนวทางปฏิบัติทั่วไปคือการใช้ gzip ในเว็บเซิร์ฟเวอร์เป็นหลักเพื่อบีบอัดทรัพยากรหน้าเว็บแบบข้อความทั่วไป เช่น ไฟล์ HTML, CSS และ JavaScript และส่งไปยังไคลเอ็นต์เพื่อทำการขยายไฟล์ ผลที่ได้คือทรัพยากรจะโหลดได้เร็วขึ้นโดยไม่ส่งผลต่อลักษณะการทํางานที่ต้องการของหน้าเว็บ

แม้ว่า Gzip จะมีประสิทธิภาพสูงอยู่แล้ว แต่การบีบอัดบนเว็บก็ได้รับการปรับปรุงเพิ่มเติมในช่วงไม่กี่ปีที่ผ่านมา ในปี 2016 อัลกอริทึม Brotli ได้เปิดตัวใน Chrome ซึ่งให้อัตราส่วนการบีบอัดโดยรวมที่ดีขึ้นสำหรับทรัพยากรที่มีสิทธิ์ ภายในสิ้นปี 2017 เบราว์เซอร์สมัยใหม่ทั้งหมดรองรับ Brotli และเซิร์ฟเวอร์ก็เริ่มรองรับ Brotli มากขึ้น เมื่อเร็วๆ นี้ Chrome ได้เริ่มใช้การบีบอัด ZStandard

แต่เรายังไม่หยุดอยู่แค่นี้ ทีม Chrome พยายามทำให้พจนานุกรมที่แชร์ใช้งานได้บนเว็บ ซึ่งตอนนี้พร้อมให้ใช้งานในการทดลองใช้เวอร์ชันต้นทางสำหรับทั้ง Brotli และ ZStandard แล้ว พจนานุกรมที่แชร์สามารถช่วยเสริมการบีบอัด Brotli และ ZStandard เพื่อให้อัตราส่วนการบีบอัดสูงขึ้นอย่างมากสําหรับเว็บไซต์ที่อัปเดตโค้ดบ่อยครั้ง และอาจให้อัตราส่วนการบีบอัด 90% ขึ้นไปได้ในบางกรณี โพสต์นี้จะอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทํางานของพจนานุกรมที่แชร์ และวิธีลงทะเบียนเข้าร่วมการทดลองใช้ต้นทางเพื่อใช้พจนานุกรมดังกล่าวกับ Brotli และ ZStandard ในเว็บไซต์

คำอธิบายพจนานุกรมที่แชร์

การบีบอัดเป็นกระบวนการค้นหาลำดับซ้ำซ้อนในอินพุต และใช้ข้อมูลดังกล่าวเพื่อสร้างเอาต์พุตที่เล็กลงมาก ซึ่งสามารถย้อนกลับได้ในภายหลัง การบีบอัดใช้งานได้ดีบนเว็บเนื่องจากช่วยลดเวลาในการโหลดทรัพยากรได้อย่างมาก ทั้ง Brotli และ ZStandard สามารถเพิ่มประสิทธิภาพได้โดยใช้พจนานุกรมการบีบอัด ซึ่งเป็นคอลเล็กชันรูปแบบเพิ่มเติมที่อัลกอริทึมเหล่านี้สามารถใช้ในระหว่างการบีบอัด อันที่จริงแล้ว Brotli มีประสิทธิภาพสูงในระดับหนึ่งด้วยการใช้พจนานุกรมภายใน

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

ต่อไปนี้คือตัวอย่างประสิทธิภาพของพจนานุกรมการบีบอัดที่กำหนดเอง สมมติว่าเว็บไซต์ของคุณใช้เฟรมเวิร์ก Angular และเวอร์ชันปัจจุบันที่คุณใช้คือ 1.7.9 เฟรมเวิร์ก Angular เวอร์ชันนี้มีขนาดประมาณ 172 KiB เมื่อไม่ได้บีบอัด เมื่อบีบอัดด้วยการตั้งค่าเริ่มต้นของ Brotli ขนาดจะอยู่ที่ประมาณ 53 KiB ซึ่งจะให้อัตราส่วนการบีบอัดเกือบ 70% แต่สมมติว่าคุณตัดสินใจอัปเกรดเป็น Angular 1.8.3 ในภายหลัง เนื่องจาก Angular เวอร์ชันนี้มีขนาดใกล้เคียงกับเวอร์ชัน 1.7.9 คุณจึงคาดหวังได้ว่าอัตราส่วนการบีบอัดจะเหมือนกับเวอร์ชันก่อนหน้า

พจนานุกรมที่กําหนดเองจะมีประโยชน์ในกรณีนี้โดยใช้กระบวนการที่เรียกว่าการบีบอัด Delta ซึ่งก็คือการใช้พจนานุกรมของทรัพยากรเวอร์ชันก่อนหน้าเพื่อบีบอัดเวอร์ชันที่ใหม่กว่า จากตัวอย่างก่อนหน้านี้ หากคุณบีบอัด Angular เวอร์ชัน 1.8.3 โดยใช้เวอร์ชัน 1.7.9 เป็นพจนานุกรม ผลลัพธ์ที่ได้จะอยู่ที่ประมาณ 4 KiB ซึ่งแสดงถึงอัตราส่วนการบีบอัดที่ เกือบ 98% เห็นได้ชัดว่าพจนานุกรมการบีบอัดอาจส่งผลอย่างมากต่อประสิทธิภาพการโหลด และประสิทธิภาพของพจนานุกรมเหล่านี้ได้เกิดขึ้นจริงแล้วในแอปพลิเคชันในชีวิตจริง

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

วิธีที่ Chrome โฆษณาการรองรับพจนานุกรมที่แชร์

เบราว์เซอร์ทั้งหมดจะแสดงอัลกอริทึมการบีบอัดที่รองรับผ่านส่วนหัวคำขอ Accept-Encoding เนื้อหาของส่วนหัวคือรายการการเข้ารหัสที่รองรับซึ่งคั่นด้วยคอมมา ดังนี้

Accept-Encoding: gzip, br, zstd

ส่วนหัว Accept-Encoding นี้ระบุว่าเบราว์เซอร์ที่ขอทรัพยากรรองรับอัลกอริทึมการบีบอัด gzip, Brotli และ ZStandard จากนั้นเว็บเซิร์ฟเวอร์ที่ตอบกลับคําขอจะเลือกอัลกอริทึมที่จะใช้ในการตอบกลับคําขอได้

เมื่อเปิดใช้การรองรับพจนานุกรมที่แชร์และมีพจนานุกรมที่เกี่ยวข้องสําหรับทรัพยากร ระบบจะเพิ่มโทเค็นเพิ่มเติมลงในส่วนหัว Accept-Encoding โทเค็นเหล่านี้คือ br-d สำหรับ Brotli และ zstd-d สำหรับ Zstandard นอกจากนี้ Chrome จะใส่แฮชของพจนานุกรมที่ใช้ได้ ซึ่งจะกล่าวถึงในลำดับถัดไป

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

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

การบีบอัดพจนานุกรมที่แชร์สำหรับทรัพยากรแบบคงที่

ทรัพยากรหน้าเว็บแบบคงที่คือทรัพยากรที่แสดงผลลัพธ์เดียวกันเสมอสําหรับ URL ที่ขอ ตัวอย่างที่พบบ่อยของทรัพยากรหน้าเว็บแบบคงที่ที่บีบอัดได้คือไฟล์ JavaScript และ CSS โดยปกติแล้ว ทรัพยากรเหล่านี้จะมีเวอร์ชันเพื่อวัตถุประสงค์ในการแคชในลักษณะใดลักษณะหนึ่ง เช่น บางครั้งอาจมีแฮชของเนื้อหาไฟล์ในชื่อไฟล์ (เช่น styles.abcd1234.css) หรือวิธีการอื่นๆ ในการระบุแหล่งที่มาของทรัพยากร ทรัพยากรประเภทเหล่านี้เหมาะอย่างยิ่งสําหรับการบีบอัดเดลต้าที่พจนานุกรมที่แชร์มีให้ เนื่องจากทรัพยากรแบบคงที่มักจะมีการแคชเป็นเวลานานและมีแนวโน้มที่จะอัปเดตเป็นประจํา

คุณสามารถระบุพจนานุกรมสําหรับทรัพยากรแบบคงที่ได้โดยการตั้งค่าส่วนหัวการตอบกลับ Use-As-Dictionary ส่วนหัวใช้คู่คีย์/ค่าคู่ใดคู่หนึ่ง แต่คู่ที่จำเป็นเพียงคู่เดียวคือ match ซึ่งยอมรับไวยากรณ์ URLPattern ที่ระบุเส้นทางทรัพยากรที่ควรใช้พจนานุกรม

Use-As-Dictionary: match="/dist/styles.*.css"

ให้คิดว่าส่วนหัว Use-As-Dictionary เป็นกลไกที่ใช้กับทรัพยากรเวอร์ชันในอนาคตที่ตรงกับรูปแบบที่ระบุไว้ สมมติว่าเว็บไซต์ของคุณแสดงสไตล์ทั้งหมดในไฟล์ CSS ไฟล์เดียว เพื่อความง่าย เราจะสมมติว่าทรัพยากรเวอร์ชันแรกนั้นอยู่ที่ /dist/styles.v1.css และส่งพร้อมกับส่วนหัวการตอบกลับ Use-As-Dictionary ที่มีค่า match เป็น /dist/styles.*.css

หลังจากผ่านไประยะหนึ่ง คุณได้อัปเดต CSS ของเว็บไซต์และเผยแพร่เวอร์ชันใหม่ใน /dist/styles.v2.css เนื่องจากค่า match ที่ใช้ในส่วนหัวการตอบกลับ Use-As-Dictionary จากเวอร์ชันก่อนหน้ามีผลกับคำขอนี้ ดังนั้นเบราว์เซอร์จะส่งส่วนหัว Available-Dictionary ที่มีแฮชของพจนานุกรมที่เข้ารหัสเป็นลำดับไบต์ของช่องที่มีโครงสร้าง ดังนี้

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

เมื่อถึงจุดนี้ ขึ้นอยู่กับเซิร์ฟเวอร์ที่จะกำหนดค่าการบีบอัดฝั่งตนเองเพื่อให้แน่ใจว่ามีการใช้พจนานุกรมที่ตรงกัน จากนั้นระบบจะส่งทรัพยากรที่บีบอัดด้วยพจนานุกรมนั้น และจะใช้พจนานุกรมที่มีอยู่ในแคชเบราว์เซอร์ของผู้ใช้เพื่อคลายการบีบอัด

หากคุณเผยแพร่โค้ดใหม่สำหรับเว็บไซต์บ่อยครั้ง การบีบอัดข้อมูลแบบเดลต้าจะมีประโยชน์อย่างมาก แต่กระบวนการนี้มีความยืดหยุ่น หากเบราว์เซอร์ไม่พบว่ามีพจนานุกรมในแคชของเบราว์เซอร์ของผู้ใช้ ก็จะไม่ระบุโทเค็น br-d หรือ zstd-d เพิ่มเติมในส่วนหัว Accept-Encoding ในกรณีนี้ ระบบจะใช้ขั้นตอนการบีบอัดมาตรฐาน

การบีบอัดพจนานุกรมที่แชร์สําหรับทรัพยากรแบบไดนามิก

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

เนื่องจากทรัพยากรที่สร้างขึ้นแบบไดนามิก คุณต้องโหลดพจนานุกรมในไคลเอ็นต์เพื่อใช้ภายหลัง การโหลดพจนานุกรมล่วงหน้าหมายความว่าการใช้การบีบอัดพจนานุกรมที่แชร์กับทรัพยากรแบบไดนามิกเป็นการคาดเดา ในกรณีเช่นนี้ หวังว่าเว็บไซต์ของคุณจะได้รับการเข้าชมมากพอที่จะกระจายค่าใช้จ่ายของพจนานุกรมไปยังการนําทางจํานวนมาก หากตัดสินใจที่จะลองใช้ ขั้นตอนแรกคือระบุตำแหน่งของพจนานุกรมผ่านองค์ประกอบ <link> ใน HTML ของหน้าเว็บ

<link rel="dictionary" href="/dictionary.dat">

เมื่อ Chrome พบองค์ประกอบ <link> นี้ อาจดึงข้อมูลพจนานุกรมเมื่อหน้าเว็บไม่มีการใช้งาน และดำเนินการนี้โดยมีลําดับความสําคัญต่ำเพื่อหลีกเลี่ยงการแย่งแบนด์วิดท์ การตอบกลับสำหรับพจนานุกรมต้องระบุส่วนหัว Use-As-Dictionary และระบุเส้นทางทรัพยากรแบบไดนามิกที่จะใช้

Use-As-Dictionary: match="/product/*"

จากตรงนี้ ขั้นตอนส่วนใหญ่จะเหมือนกับทรัพยากรแบบคงที่ เบราว์เซอร์จะเห็นว่าพจนานุกรมมีผลกับทรัพยากรที่ตรงกันและจะแนบส่วนหัว Available-Dictionary ไปกับคำขอพร้อมแฮชของเนื้อหาพจนานุกรม ซึ่งก็คล้ายกับขั้นตอนทรัพยากรแบบคงที่ที่อธิบายไว้ก่อนหน้านี้

บีบอัดทรัพยากรแบบคงที่เมื่อสร้าง

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

เครื่องมือจัดกลุ่มที่ใช้ Node.js ส่วนใหญ่ที่รองรับการบีบอัดจะใช้ไลบรารี Zlib ในตัวของ Node Zlib รองรับ Brotli และเครื่องมือรวมที่ใช้ Brotli มักจะมีอินเทอร์เฟซในการส่งตัวเลือกไปยัง Zlib โดยตรง ซึ่งรองรับการบีบอัดด้วยพจนานุกรม เครื่องมือจัดกลุ่มที่รองรับการใช้พจนานุกรมมีดังนี้

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

ลองใช้เลย!

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

  1. หากต้องการลองใช้การบีบอัดพจนานุกรมที่แชร์ด้วยตนเองเพื่อดูวิธีการทํางาน คุณสามารถเปิดใช้ฟีเจอร์ทดลองการรับส่งพจนานุกรมการบีบอัดในหน้า chrome://flags
  2. หากสนใจลองใช้ฟีเจอร์นี้ในเว็บไซต์เวอร์ชันที่ใช้งานจริงและดูว่าการบีบอัดพจนานุกรมที่แชร์จะเป็นประโยชน์ต่อผู้ใช้จริงได้อย่างไร ให้ลงทะเบียนเข้าร่วมการทดลองใช้เวอร์ชันที่ใช้งานจริงเพื่อรับโทเค็น และอ่านวิธีการทํางานของการทดลองใช้เวอร์ชันที่ใช้งานจริง

บทสรุป

เรารู้สึกตื่นเต้นกับการพัฒนาครั้งสำคัญนี้ในเทคโนโลยีการบีบอัดบนเว็บ และความเร็วที่เพิ่มขึ้นของแอปพลิเคชันที่มีอยู่ซึ่งผู้คนใช้ทุกวัน เราขอแนะนำให้คุณลองใช้ฟีเจอร์นี้ และที่สำคัญที่สุดคือเราอยากฟังความคิดเห็นของคุณหากลองใช้ หากพบข้อบกพร่อง โปรดรายงานที่ crbug.com ดูแหล่งข้อมูลและเครื่องมือเพิ่มเติมได้ที่ use-as-dictionary.com และสุดท้าย หากคุณสนใจที่จะเจาะลึกวิธีการทำงานของฟีเจอร์นี้ โปรดดูคำอธิบาย