משפרים את יעילות הדחיסה עם מילונים משותפים

דחיסת נתונים היא שיטה לאופטימיזציה של ביצועים שנבדקת זמן רב, שמפחיתה את גודל המשאבים שעומדים בדרישות בדף. במשך זמן מה, היה מקובל להשתמש בעיקר ב-gzip בשרתי אינטרנט כדי לדחוס משאבים נפוצים בדפים מבוססי-טקסט, כגון HTML, קובצי CSS וקובצי JavaScript, ולשלוח אותם ללקוח, לשם פענוח הדחיסה שלהם. התוצאה היא זמני טעינה מהירים יותר של משאבים מבלי להשפיע על ההתנהגות הרצויה של הדף.

על אף ש-gzip יעיל מאוד בפני עצמו, בשנים האחרונות ניכרו שיפורים נוספים בדחיסת הנתונים באינטרנט. בשנת 2016, אלגוריתם Brotli יצא לשימוש ב-Chrome ושיפר באופן כללי יחסי דחיסה טובים יותר למשאבים שעומדים בדרישות. עד סוף 2017, כל הדפדפנים המודרניים תמכו ב-Brotli, והתמיכה בשרת הפכה לנפוצה יותר. לאחרונה, Chrome שלח את ZStandard compression.

אבל העבודה עוד לא נגמרה. צוות Chrome עובד על כך שניתן יהיה להשתמש במילונים משותפים באינטרנט, שזמינים עכשיו בגרסת המקור לניסיון של Brotli ו-ZStandard. המילונים המשותפים יכולים להשלים את הדחיסה של Brotli ו-ZStandard, וכך לספק יחסי דחיסה גבוהים יותר באופן משמעותי לאתרים ששולחים קוד מעודכן לעיתים קרובות. הם גם יכולים, במקרים מסוימים, לספק יחסי דחיסה של 90% או יותר. בפוסט הזה נסביר יותר על אופן הפעולה של מילונים משותפים, ואיך להירשם לגרסאות המקור לניסיון כדי להשתמש בהם ב-Brotli וב-ZStandard באתר שלך.

הסבר על מילונים משותפים

דחיסה היא תהליך של מציאת רצפים מיותרים בקלט ושימוש במידע הזה כדי ליצור פלט הרבה יותר קטן, שאותו אפשר להפוך בהמשך. דחיסה פועלת היטב באינטרנט כי היא מפחיתה באופן משמעותי את זמני הטעינה של משאבים. גם Brotli וגם ZStandard יכולים להגביר את היעילות שלהם באמצעות מילון דחיסה, שהוא אוסף של תבניות נוספות שבהן האלגוריתמים האלה יכולים להשתמש במהלך הדחיסה. למעשה, היעילות הגבוהה של Brotli מושגת במידה מסוימת באמצעות שימוש במילון פנימי.

עם זאת, ניתן להשתמש במילונים מותאמים אישית שנאספו על ידי משתמשים עם Brotli ו-ZStandard שמכילים דפוסים ספציפיים למשאבים מסוימים. בפועל, מילון מותאם אישית הוא קובץ חיצוני שאפשר להחיל על כל קלט. מילונים יכולים להיות ספציפיים מאוד לקוד הייצור של אפליקציה, או לכל תוכן בכלל. מידת הרלוונטיות של מילון נתון לקלט שלו יכולה להשפיע באופן משמעותי על יעילות הדחיסה הכוללת. מילונים שדומים מאוד לתוכן הקלט ייצרו פלט עם יחסי דחיסה גבוהים יותר מאשר מילונים עם תכנים כלליים או לא דומים.

הנה דוגמה למידת היעילות של מילון דחיסה מותאם אישית: נניח שהאתר שלך משתמש במסגרת Angular, והגרסה הנוכחית שבה אתה משתמש היא גרסה 1.7.9. הגרסה הזו של Angular framework היא בערך 172KiB לא דחוסה. כשדוחסים אותו עם הגדרות ברירת המחדל של Brotli, הגודל שלו הופך ל-53KiB בערך. כך אפשר לקבל יחס דחיסה של כמעט 70%. עם זאת, נניח שתחליטו לשדרג ל-Angular 1.8.3 מאוחר יותר. מכיוון שהגרסה הזו של Angular זהה בגודלה לגרסה 1.7.9, ניתן לצפות ליחס הדחיסה פחות או יותר כמו הגרסה הקודמת.

כאן מילון מותאם אישית יכול להיות שימושי באמצעות תהליך הנקרא דחיסת דלתא. כלומר , ניתן להשתמש במילון של גרסה קודמת של משאב כדי לדחוס גרסה מאוחרת יותר. בהמשך לדוגמה הקודמת, אם דחסתם את גרסה 1.8.3 של Angular באמצעות גרסה 1.7.9 כמילון, הפלט יהיה עם מעט יותר מ-4KiB. ערך זה מייצג יחס דחיסה של כמעט 98%. ברור שלמילוני דחיסה יכולה להיות השפעה משמעותית על ביצועי הטעינה, והיעילות שלהם כבר מיושמת באפליקציות בעולם האמיתי!

עם זאת, קיים אתגר ביצירת התהליך הזה באינטרנט. למשל, אם משתמשים במילון כדי לדחוס משאב, צריך את אותו המילון כדי לפרוס את הדחיסה. ניסיתם בעבר את התהליך הזה באינטרנט, כלומר SDCH, אבל היה קשה להטמיע אותו בצורה בטוחה. ההצעה האחרונה לדחיסת מילונים משותפת מטפלת בבעיות האלה ומספקת תועלת משמעותית למשאבים סטטיים ודינמיים גם יחד.

איך מפרסמים ב-Chrome תמיכה במילונים משותפים

כל הדפדפנים מפרסמים את אלגוריתמי הדחיסה שבהם הם תומכים באמצעות כותרת הבקשה Accept-Encoding. התוכן של הכותרת הוא רשימה של קידודים נתמכים שמופרדים בפסיקים:

Accept-Encoding: gzip, br, zstd

כותרת Accept-Encoding המסוימת הזו מציינת שהדפדפן שמבקש את המשאב תומך באלגוריתמים של הדחיסה gzip, Brotli ו-ZStandard. לאחר מכן, שרת אינטרנט שמגיב לבקשה יכול להחליט באיזה אלגוריתם להשתמש בתגובה לבקשה.

כשמופעלת תמיכה במילון משותף ומילון רלוונטי זמין למשאב, אסימונים נוספים מתווספים לכותרת Accept-Encoding. האסימונים האלה הם br-d ל-Brotli ו-zstd-d ל-Zstandard. Chrome יכלול גם את הגיבוב (hash) של מילון זמין, בנושא.

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

אם שרת אינטרנט מוגדר לזהות את האסימון הזה והוא מזהה את המילון, הוא יכול להגיב לבקשה הזו באמצעות משאב שנדחס באמצעות המילון עבור הקידוד הרלוונטי. האופן שבו זה יושג בפועל תלוי בשאלה אם הבקשה היא למשאב סטטי או דינמי.

דחיסת מילון משותף עבור משאבים סטטיים

משאב סטטי בדף הוא כזה שמפיק תמיד את אותה תגובה לכתובת URL מבוקשת. דוגמאות נפוצות למשאבים סטטיים של דפים הם קובצי JavaScript ו-CSS. בדרך כלל, גרסאות המשאבים האלה משמשות למטרות שמירה במטמון בדרך כלשהי – לפעמים באמצעות גיבוב (hash) של תוכן הקובץ בשם הקובץ (לדוגמה 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 לבקשה עם גיבוב של תוכן המילון, שוב, בדומה לתהליך המשאבים הסטטי שהוסבר קודם לכן.

דחיסת משאבים סטטיים בזמן ה-build

אם אתם מכירים את הכלים הדחוסים, ייתכן שאתם מכירים יישומי פלאגין שונים שיכולים לדחוס משאבים בזמן ה-build, ולאחר מכן להציג את המשאבים הדחוסים האלה. לדוגמה, Apache מאפשר להשתמש בהוראות כדי למלא את המשאבים הדחוסים מראש בזמן הבקשה.

רוב המארזים המבוססים על Node.js שתומכים בדחיסה משתמשים בספריית Zlib המובנית של Node. Zlib מציע תמיכה ל-Brotli ול-Bundlers שמשתמשים בדרך כלל בממשק להעברת אפשרויות ישירות ל-Zlib, שתומך בדחיסה בעזרת מילון. הנה כמה רכיבי Bundle שתומכים בשימוש במילונים:

שים לב שהמילונים הזמינים לכל גרסה נתונה של משאב עשויים להשתמש באחת מהגרסאות הקודמות של המשאב. כלומר, עליכם לנתח את תנועת המשתמשים ולתכנן בהתאם. השתדלו להגיע לאיזון וצרו משאבים שיעזרו ככל האפשר למספר המקסימלי של משתמשים חוזרים. ספקי CDN עורכים כרגע ניסויים עם דחיסת מילון משותף. אין עדיין יישומים זמינים לשימוש ציבורי, אבל אנחנו מצפים שזה ישתנה!

כדאי לנסות!

שילוב של דחיסת מילון משותף עם יכולות הדחיסה הקיימות של הדפדפן עשוי לשפר באופן משמעותי את ביצועי הטעינה באתרים ששולחים לעתים קרובות קוד ייצור מעודכן ומקבלים תנועה משמעותית ממבקרים חוזרים. אם רוצים לנסות דחיסת מילון משותף, יש שתי אפשרויות:

  1. אם אתם רוצים להתנסות בדחיסת מילון משותף בעצמכם כדי להבין איך זה עובד, תוכלו להפעיל את התכונה הניסיונית העברה של מילון דחיסה בדף chrome://flags.
  2. אם אתם רוצים לנסות את האפשרות הזו באתר הייצור שלכם ולראות איך דחיסת מילונים משותפת יכולה להועיל למשתמשים אמיתיים, הירשמו לגרסת המקור לניסיון כדי לקבל אסימון וקראו איך פועלות גרסאות המקור לניסיון.

סיכום

אנחנו נרגשים למדי מההתקדמות המשמעותית הזו בטכנולוגיית הדחיסה באינטרנט, ולגבי המהירות שבה היא יכולה להפוך אפליקציות קיימות שאנשים משתמשים בהן מדי יום. אנחנו ממליצים לך לנסות אותה, והכי חשוב – אנחנו רוצים לשמוע מה דעתך. אם מצאתם באג, דווחו עליו בכתובת crbug.com. לקבלת מקורות מידע וכלים נוספים, מומלץ להיכנס לכתובת use-as-dictionary.com. לסיום, אם אתם מעוניינים להתעמק בהסבר על התהליך, מומלץ להיעזר בתיאור התהליך.