שדרו את הדרך שלכם לתגובות מיידיות

כל מי שהשתמש ב-service workers יכול לומר שהם אסינכרונים לכל אורך הדרך. הם מסתמכים אך ורק על ממשקים מבוססי-אירועים, כמו FetchEvent, ומשתמשים בהבטחות כדי לסמן מתי פעולות אסינכרוניות מסתיימות.

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

כשכותבים טיפול אירועים משלכם של fetch, נהוג פשוט להעביר לשיטה respondWith() את הערך של Response (או הבטחה ל-Response) שמקבלים דרך fetch() או caches.match(), ולהפסיק שם. החדשות הטובות הן שכבר אפשר להעביר בסטרימינג את ה-Response שנוצרו בשתי השיטות האלה. החדשות הרעות הן שאי אפשר להעביר Responses שנבנו 'באופן ידני', לפחות עד עכשיו. כאן נכנס לתמונה Streams API.

Streams?

מקור נתונים הוא מקור נתונים שאפשר ליצור ולבצע בו פעולות באופן מצטבר, והוא מספק ממשק לקריאה או לכתיבה של קטעי נתונים אסינכרונים, שרק קבוצת משנה שלהם עשויה להיות זמינה בזיכרון בכל זמן נתון. בשלב הזה, אנחנו מתעניינים ב-ReadableStreams, שאפשר להשתמש בהם כדי ליצור אובייקט Response שמוענק ל-fetchEvent.respondWith():

self.addEventListener('fetch', event => {
    var stream = new ReadableStream({
    start(controller) {
        if (/* there's more data */) {
        controller.enqueue(/* your data here */);
        } else {
        controller.close();
        }
    });
    });

    var response = new Response(stream, {
    headers: {'content-type': /* your content-type here */}
    });

    event.respondWith(response);
});

הדף שהבקשה שלו גרמה לאירוע fetch תקבל תשובה בסטרימינג ברגע שהקריאה ל-event.respondWith() תתבצע, והוא ימשיך לקרוא מהסטרימינג הזה כל עוד קובץ השירות ממשיך ל-enqueue() נתונים נוספים. התגובה שמגיעה מקובץ השירות לדף היא באמת אסינכרונית, ויש לנו שליטה מלאה על מילוי הסטרימינג.

שימושים בעולם האמיתי

כנראה שמתם לב שבדוגמה הקודמת היו כמה תגובות placeholder‏ /* your data here */, והיא לא כללה פרטי הטמעה בפועל. איך נראית דוגמה מהעולם האמיתי?

ג'ייק ארקדיל (Jake Archibald) (לא מפתיע!) מציג דוגמה מצוינת לשימוש בסטרימינג כדי לחבר יחד תגובה ב-HTML מכמה קטעי HTML שנשמרו במטמון, יחד עם נתונים 'בזמן אמת' שמועברים בסטרימינג דרך fetch() – במקרה הזה, תוכן לבלוג שלו.

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

Streams? או מעטפות של אפליקציות?

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

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

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

אם אתם בשלב התכנון של הטמעת ה-service worker, איזה מודל כדאי לכם לאמץ: תגובות בסטרימינג שמעבדים באופן הדרגתי או מעטפת קלה בשילוב עם בקשה מצד הלקוח לתוכן דינמי? התשובה היא, לא מפתיע, שהיא תלויה בדברים הבאים: אם יש לכם הטמעה קיימת שמסתמכת על מערכת ניהול תוכן ותבניות חלקיות (יתרון: סטרימינג), אם אתם מצפים לעומסי נתונים גדולים של HTML בודדים שיהיו להם יתרונות מעיבוד הדרגתי (יתרון: סטרימינג), אם הכי מתאים ליצור מודל לאפליקציית האינטרנט שלכם כאפליקציה של דף יחיד (יתרון: פגז אפליקציה) ואם אתם צריכים מודל שנתמך כרגע במהדורות יציבות של כמה דפדפנים (יתרון: פגז אפליקציה).

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

התעמקות בנתוני הסטרימינג

אם אתם יוצרים מקורות נתונים לקריאה בעצמכם, יכול להיות שקריאה פשוטה של controller.enqueue() ללא הבחנה לא תהיה מספקת או יעילה. ג'ייק מתאר בפירוט איך אפשר להשתמש בשילוב בשיטות start(),‏ pull() ו-cancel() כדי ליצור מקור נתונים מותאם אישית לתרחיש לדוגמה.

רוצים לקבל פרטים נוספים? המפרט של Streams יעזור לכם.

תאימות

התמיכה ביצירת אובייקט Response בתוך עובד שירות באמצעות ReadableStream כמקור שלו נוספה ב-Chrome 52.

הטמעת ה-service worker ב-Firefox עדיין לא תומכת בתשובות שמגובות ב-ReadableStream, אבל יש באג מעקב רלוונטי לתמיכה ב-Streams API שאפשר לעקוב אחריו.

כדי לעקוב אחרי ההתקדמות בתמיכה ב-Streams API ללא קידומת ב-Edge, וגם אחרי התמיכה הכוללת ב-service worker, אפשר להיכנס לדף סטטוס הפלטפורמה של Microsoft.