بث مباشر لتلقّي ردود فورية

يمكن لأي شخص استخدم عاملي الخدمة أن يخبرك بأنهم غير متزامنين طوال العملية. وتعتمد هذه الأنظمة حصريًا على الواجهات المستندة إلى الأحداث، مثل FetchEvent، كما أنّها تستخدم الوعود التي توفّر إشارة عند اكتمال العمليات غير المتزامنة.

عدم المزامنة مهم بنفس القدر، حتى لو كان أقل وضوحًا للمطوّر، وذلك عندما يتعلق الأمر بالاستجابات التي يوفّرها معالج أحداث الاسترجاع لدى مشغّل الخدمات. وتمثّل الردود الخاصة بالبث معيارًا ذهبيًا، فهي تسمح للصفحة التي قدّمت الطلب الأصلي ببدء الاستجابة للاستجابة فور توفُّر أوّل دفعة من البيانات، ويمكن أن تستخدم برامج تحليل محسَّنة للبث لعرض المحتوى تدريجيًا.

عند كتابة معالج أحداث fetch الخاص بك، من الشائع أن تطبِّق طريقة respondWith() Response (أو وعدًا بـ Response) تحصل عليه عبر fetch() أو caches.match()، واطلق عليه يومًا واحدًا. يسرّنا إعلامك بأنّ فيديوهات Response التي تم إنشاؤها باستخدام هاتين الطريقتين يمكن بثها مباشرةً. من ناحية أخرى، الخبر غير السار هو أنّ "Response" التي تم إنشاؤها يدويًا غير قابلة للبث، على الأقل حتى الآن. هذا هو المكان الذي يتم فيه إدخال الصورة بواسطة Streams API.

ساحات المشاركات؟

ساحة المشاركات هي مصدر بيانات يمكن إنشاؤه ومعالجتها بشكل تدريجي، وتوفّر واجهة لقراءة أو كتابة أجزاء غير متزامنة من البيانات، قد تتوفّر فقط مجموعة فرعية منها في الذاكرة في أي وقت معيّن. في الوقت الحالي، يهمّنا استخدام ReadableStream، التي يمكن استخدامها لإنشاء كائن 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()الحصول على بيانات إضافية. إنّ الاستجابة الواردة من مشغّل الخدمات إلى الصفحة غير متزامنة حقًا، ويمكننا التحكّم بشكل كامل في ملء ساحة المشاركات.

الاستخدامات الفعلية

لعلّك لاحظت أنّ المثال السابق تضمّن بعض تعليقات /* your data here */ النائبة، وكان يسلّط الضوء على تفاصيل التنفيذ الفعلي. إذًا كيف سيبدو مثالًا من العالم الحقيقي؟

يقدّم جايك أرشيبالد (ليس من المستغرب) مثالاً رائعًا على استخدام ساحات المشاركات لجمع استجابة HTML معًا من مقتطفات HTML مخزّنة مؤقتًا، بالإضافة إلى البيانات "المباشرة" التي يتم بثها عبر fetch()، وهي في هذه الحالة محتوى مدونته

وتتمثّل فائدة استخدام استجابة البث، كما أوضح جايك، في أنّ المتصفح يمكنه تحليل محتوى HTML وعرضه أثناء بثه، بما في ذلك وحدة البت الأول التي يتم تحميلها بسرعة من ذاكرة التخزين المؤقت، بدون الحاجة إلى الانتظار حتى اكتمال عملية جلب محتوى المدونة بالكامل. ويمكنك الاستفادة إلى أقصى حد من إمكانات عرض HTML التدريجي في المتصفح. يمكن للموارد الأخرى التي يمكن عرضها تدريجيًا، مثل بعض تنسيقات الصور والفيديوهات، أن تستفيد أيضًا من هذا النهج.

ساحات المشاركات؟ أو هيكل التطبيقات؟

تركّز أفضل الممارسات الحالية المتعلّقة باستخدام مشغِّلي الخدمات لتعزيز تطبيقات الويب على نموذج App Shell + المحتوى الديناميكي. ويعتمد هذا المنهج على التخزين المؤقت "لهيكل" تطبيق الويب، أي الحد الأدنى من رموز HTML وJavaScript وCSS اللازمة لعرض البنية والتنسيق، ثم تحميل المحتوى الديناميكي المطلوب لكل صفحة محددة من خلال طلب من جهة العميل.

وتجلب ساحات المشاركات إليها بديلاً لنموذج App Shell، حيث يتم بث استجابة HTML كاملة إلى المتصفِّح عند انتقال المستخدم إلى صفحة جديدة. يمكن للاستجابة المتدفقة الاستفادة من الموارد المخزّنة مؤقتًا، بحيث لا يزال بإمكانها توفير المقطع الأولي من HTML بسرعة، حتى أثناء عدم الاتصال بالإنترنت. وفي نهاية المطاف، تبدو أشبه بنصوص استجابة تقليدية يعرضها الخادم. على سبيل المثال، إذا كان تطبيق الويب مستندًا إلى نظام إدارة محتوى يعرض الخادم رمز HTML من خلال تجميع النماذج الجزئية معًا، سيتحول هذا النموذج مباشرةً إلى استخدام الردود المباشرة، مع منطق النموذج الذي يتم تكراره في مشغّل الخدمات بدلاً من الخادم. وكما يبيّن الفيديو التالي، بالنسبة إلى حالة الاستخدام هذه، يمكن أن تكون ميزة السرعة التي تقدمها الردود مباشرة مذهلة:

من بين الميزات المهمة لبث استجابة HTML بالكامل، التي توضّح سبب أنها أسرع بديل في الفيديو، أنّ HTML الذي يتم عرضه أثناء طلب التنقل الأولي يمكنه الاستفادة الكاملة من محلّل HTML للبث في المتصفح. إنّ مقاطع HTML التي يتم إدراجها في مستند بعد تحميل الصفحة (كما هو شائع في نموذج App Shell) لا يمكنها الاستفادة من هذا التحسين.

لذلك، إذا كنت في مراحل التخطيط لتنفيذ مشغّل الخدمات، فما النموذج الذي يجب أن تتّبعه: الردود المتدفقة التي يتم عرضها تدريجيًا، أو هيكل خفيف مع طلب من جهة العميل للمحتوى الديناميكي؟ ولا عجب في ذلك أنّ الأمر يعتمد على ما إذا كان لديك تطبيق حالي يعتمد على نظام إدارة محتوى (CMS) ونماذج جزئية (الميزة: البث)، وما إذا كنت تتوقع أعداد HTML الكبيرة والمفردة التي ستستفيد من العرض التدريجي (الميزة: البث)، وما إذا كان تطبيق الويب الخاص بك مصمَّمًا بشكل أفضل كتطبيق من صفحة واحدة (ميزة: إصدار App Shell: متوافق مع العديد من المتصفحات).

ما زلنا في الأيام الأولى من تلقّي ردود البث من العاملين في الخدمة، ونتطلّع إلى رؤية النماذج المختلفة تنضج، وبشكل خاص رؤية المزيد من الأدوات التي تم تطويرها لبرمجة حالات الاستخدام الشائعة.

نظرة معمّقة على ساحات المشاركات

إذا كنت تنشئ ساحات مشاركات خاصة بك سهلة القراءة، قد لا يكفي طلب controller.enqueue() بشكل عشوائي أو استخدامها بشكل فعّال. يقدّم "جيك" بعض التفاصيل حول كيفية استخدام طرق start() وpull() وcancel() جنبًا إلى جنب لإنشاء مصدر بيانات مخصّص لحالة استخدامك.

ويمكن الاطّلاع على مواصفات ساحات المشاركات لمعرفة المزيد من التفاصيل.

التوافق

إتاحة إنشاء عنصر Response داخل مشغّل الخدمات باستخدام ReadableStream حيث تمت إضافة مصدره في Chrome 52.

لا يتوافق تطبيق مشغّل الخدمات في Firefox حتى الآن مع الردود المتوافقة مع ReadableStreams، ولكن هناك خطأ تتبُّع ذو صلة لدعم واجهة برمجة تطبيقات Streams يمكنك متابعته.

يمكن تتبُّع مستوى التقدّم في التوافق مع واجهة برمجة تطبيقات Streams API غير المسبوقة في Edge، بالإضافة إلى دعم مشغّلي الخدمات العام، وذلك من خلال صفحة حالة النظام الأساسي من Microsoft.