برمجة نصية لعامل الخدمة

يشكّل هذا الدرس التطبيقي جزءًا من الدورة التدريبية"تطوير تطبيقات الويب التقدّمية"ومطوّري البرامج التي طوّرها فريق تدريب Google Developers. ستحصل على أقصى قيمة من هذه الدورة التدريبية إذا كنت تعمل من خلال الدروس التطبيقية حول الترميز بالتسلسل.

للحصول على التفاصيل الكاملة حول الدورة التدريبية، راجع نظرة عامة على تطوير تطبيقات الويب التقدّمية.

مقدمة

يرشدك هذا الدرس التطبيقي إلى كيفية إنشاء مشغّل خدمات بسيط ويوضّح دورة حياة مشغّل الخدمات.

ما ستتعرَّف عليه

  • أنشئ نصًا برمجيًا أساسيًا لعامل الخدمة، وثبِّته، ونفِّذ تصحيح الأخطاء البسيط.

ما يتعين عليك معرفته

  • JavaScript وHTML الأساسيان
  • المفاهيم والبنية الأساسية في ES2015 الوعود
  • كيفية تفعيل وحدة تحكّم مطوّري البرامج

ما تحتاج إليه قبل البدء

يمكنك تنزيل مستودع pwa-training-labs أو استنساخه من github وتثبيت إصدار LTS من Node.js، إذا لزم الأمر.

انتقِل إلى الدليل service-worker-lab/app/ وابدأ خادم التطوير المحلي:

cd service-worker-lab/app
npm install
node server.js

يمكنك إنهاء الخادم في أي وقت باستخدام Ctrl-c.

افتح المتصفّح وانتقِل إلى localhost:8081/.

ملاحظة: ألغِ تسجيل أي عاملي خدمة وامحُ جميع ذاكرات التخزين المؤقت لعامل الخدمة في ما يتعلق بالمضيف المحلي حتى لا تتداخل مع الدرس التطبيقي. في Chrome DevTools، يمكنك تنفيذ ذلك بالنقر على محو بيانات الموقع الإلكتروني من قسم محو مساحة التخزين من علامة التبويب التطبيق.

افتح مجلد service-worker-lab/app/ في محرِّر النصوص المفضَّل لديك. المجلد app/ هو المكان الذي سيتم إنشاء الدرس التطبيقي فيه.

يحتوي هذا المجلد على:

  • below/another.html وjs/another.js وjs/other.js وother.html هي نماذج للموارد التي نستخدمها لتجربة نطاق مشغّل الخدمات
  • يتضمّن المجلد styles/ أوراق الأنماط المتتالية لهذا الدرس التطبيقي.
  • يحتوي مجلد test/ على ملفات لاختبار مدى تقدُّمك.
  • index.html هي صفحة HTML الرئيسية لنموذج الموقع/التطبيق
  • service-worker.js هو ملف JavaScript الذي يُستخدم لإنشاء مشغّل الخدمات
  • يتتبع package.json وpackage-lock.json حزم العُقد المستخدمة في هذا المشروع
  • server.js هو خادم النسخ الاحتياطي السريع الذي نستخدمه لاستضافة تطبيقنا.

افتح service-worker.js في محرِّر النصوص. لاحظ أن الملف فارغ. لم نُضِف أي رمز للتشغيل داخل مشغّل الخدمات حتى الآن.

افتح index.html في محرِّر النصوص.

داخل علامات <script>، أضِف الرمز التالي لتسجيل مشغّل الخدمات:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('service-worker.js')
    .then(registration => {
      console.log('Service Worker is registered', registration);
    })
    .catch(err => {
      console.error('Registration failed:', err);
    });
  });
}

احفظ النص البرمجي وأعِد تحميل الصفحة. يجب أن تعرض وحدة التحكم رسالة تشير إلى تسجيل مشغّل الخدمات. في Chrome، يمكنك التحقّق من أنّ مشغّل الخدمات مسجّل من خلال فتح أدوات مطوري البرامج (Control + Shift + I على نظامي التشغيل Windows وLinux) أو ⌘ + alt + I على نظام التشغيل Mac)، والنقر على علامة التبويب Application، ثم النقر على الخيار Service Workers. من المفترض أن يظهر لك ما يشبه ما يلي:

اختياري: افتح الموقع الإلكتروني على متصفّح غير متوافق وتحقَّق من عمل فحص التوافق بشكل مشروط.

الشرح

يسجّل الرمز أعلاه ملف service-worker.js بصفته مشغّل الخدمات. وتتحقق هذه السياسة أولاً مما إذا كان المتصفّح يتوافق مع مقدّمي الخدمات. ويجب أن يتم ذلك في كل مرة تسجّل فيها مشغّل خدمات لأنّ بعض المتصفحات قد لا تتوافق مع مشغّلي الخدمات. يسجّل الرمز بعد ذلك مشغّل الخدمات باستخدام طريقة register في ServiceWorkerContainer API، المضمّنة في واجهة Navigator من النافذة.

تعرض navigator.serviceWorker.register(...) وعودًا يتم حلها باستخدام كائن registration بعد تسجيل مشغّل الخدمات بنجاح. وفي حال تعذّر التسجيل، سيتم رفض الوعد.

التغييرات التي تطرأ على حالة مشغّل الخدمات تؤدي إلى تشغيل الأحداث في مشغّل الخدمات.

إضافة أدوات معالجة الأحداث

افتح service-worker.js في محرِّر النصوص.

أضِف أدوات معالجة الحدث التالية إلى مشغّل الخدمات:

self.addEventListener('install', event => {
  console.log('Service worker installing...');
  // Add a call to skipWaiting here
});

self.addEventListener('activate', event => {
  console.log('Service worker activating...');
});

احفظ الملف.

إلغاء تسجيل مشغّل الخدمات يدويًا وإعادة تحميل الصفحة لتثبيت مشغّل الخدمات المعدَّل وتفعيله يجب أن يشير سجلّ وحدة التحكّم إلى أنه تم تسجيل مشغّل الخدمات الجديد وتثبيته وتفعيله.

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

الشرح

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

عندما يكون مشغّل الخدمات مسجّلاً، يرصد المتصفّح ما إذا كان مشغّل الخدمات جديدًا (إما لأنّه يختلف عن مشغّل الخدمات المثبّت مسبقًا أو بسبب عدم توفّر مشغّل خدمات مسجّل لهذا الموقع الإلكتروني). وفي حال كان مشغّل الخدمات جديدًا (كما هو في هذه الحالة)، سيثبِّته المتصفِّح.

يصدر مشغّل الخدمات حدث activate عندما يتحكم في الصفحة. يسجّل الرمز أعلاه رسالة هنا، ولكن غالبًا ما يتم استخدام هذا الحدث لتحديث ذاكرات التخزين المؤقت.

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

ملاحظة: لا يكفي إعادة تحميل الصفحة لنقل عنصر التحكّم إلى مشغّل خدمات جديد، لأنه سيتم طلب الصفحة الجديدة قبل إلغاء تحميل الصفحة الحالية، ولن يتوفّر وقت لا يكون فيه عامل الخدمة القديم قيد الاستخدام.

ملاحظة: يمكنك أيضًا تفعيل مشغّل خدمات جديد يدويًا باستخدام بعض المتصفّحات&#39؛ وأداة مطوّري البرامج آليًا من خلال skipWaiting()، وهو ما سنناقشه في القسم 3.4.

تعديل مشغّل الخدمات

يمكنك إضافة التعليق التالي في أي مكان في service-worker.js:

// I'm a new service worker

احفظ الملف وأعِد تحميل الصفحة. انظر إلى السجلّات في وحدة التحكّم. لاحظ أن مشغّل الخدمات الجديد يثبّت ولكن لا يتم تفعيله. في متصفِّح Chrome، يمكنك الاطّلاع على مشغّل خدمات الانتظار في علامة التبويب التطبيق في "أدوات مطوري البرامج".

أغلِق جميع الصفحات المرتبطة بمشغّل الخدمة. ثم أعِد فتح localhost:8081/. يجب أن يشير سجلّ وحدة التحكُّم إلى تفعيل مشغِّل الخدمات الجديد الآن.

ملاحظة: في حال تلقّي نتائج غير متوقَّعة، تأكّد من إيقاف ذاكرة التخزين المؤقت عبر HTTP في أدوات المطوّرين.

الشرح

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

تخطي مرحلة الانتظار

من الممكن لعامل خدمة جديد التفعيل فورًا، حتى إذا كان مشغّل الخدمات الحالي موجودًا من خلال تخطي مرحلة الانتظار.

في service-worker.js، أضِف مكالمة إلى skipWaiting في أداة معالجة حدث install:

self.skipWaiting();

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

الشرح

تسمح الطريقة skipWaiting() مشغّل الخدمات بتفعيله فور الانتهاء من التثبيت. وتُعدّ أداة معالجة حدث التثبيت مكانًا شائعًا لإجراء طلب skipWaiting()، ولكن يمكن طلبها في أي مكان أثناء مرحلة الانتظار أو قبلها. راجِع هذه المستندات للحصول على مزيد من المعلومات حول وقت استخدام skipWaiting() وطريقة استخدامه. بالنسبة إلى بقية الدرس التطبيقي، يمكننا الآن اختبار رمز مشغّل الخدمات الجديد بدون إلغاء تسجيل مشغّل الخدمات يدويًا.

للحصول على معلومات إضافية

يمكن للعاملين في الخدمة العمل كخادم وكيل بين تطبيق الويب والشبكة.

لنضيف مستمعًا لجلب اعتراض الطلبات من نطاقنا.

إضافة الرمز التالي إلى service-worker.js:

self.addEventListener('fetch', event => {
  console.log('Fetching:', event.request.url);
});

احفظ النص البرمجي وأعِد تحميل الصفحة لتثبيت مشغّل الخدمات المعدَّل وتفعيله.

تحقق من وحدة التحكم ولاحظ أنه لم يتم تسجيل أي أحداث جلب. أعِد تحميل الصفحة ثم تحقَّق من وحدة التحكم مرة أخرى. من المفترض أن ترى أحداث جلب الصفحة هذه المرة ومواد العرض (مثل CSS).

انقر على الروابط المؤدية إلى صفحة أخرى وصفحة أخرى ورجوع.

سترى أحداث الجلب في وحدة التحكم لكل صفحة من الصفحات ومواد العرض المتعلقة بها. هل تقدّم جميع السجلات معنى؟

ملاحظة: إذا انتقلت إلى صفحة ولم يتم إيقاف ذاكرة التخزين المؤقت عبر HTTP، قد يتم تخزين مواد عرض CSS وJavaScript في ذاكرة التخزين المؤقت محليًا. وإذا حدث ذلك، لن ترى أحداث جلب لهذه الموارد.

الشرح

يتلقّى مشغّل الخدمات حدث جلب لكل طلب HTTP يتم إجراؤه من خلال المتصفّح ضمن نطاقه. يحتوي كائن جلب الحدث على الطلب. الاستماع إلى أحداث الجلب في مشغّل الخدمات يشبه الاستماع إلى أحداث النقر في DOM. في الرمز الخاص بنا، عندما يحدث حدث جلب، نسجِّل عنوان URL المطلوب إلى وحدة التحكُّم (ومن الناحية العملية، يمكننا أيضًا إنشاء ردّ مخصَّص وعرضه بموارد عشوائية).

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

للحصول على معلومات إضافية

رمز الحلّ

للحصول على نسخة من رمز العمل، انتقل إلى مجلد 04-intercepting-network-requests/.

مشغّلو الخدمات لديهم نطاق. يحدّد نطاق مشغّل الخدمات المسارات التي يعترض عليها مشغّل الخدمات الطلبات.

البحث عن النطاق

عليك تعديل رمز التسجيل في index.html باستخدام:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('service-worker.js')
    .then(registration => {
      console.log('SW registered with scope:', registration.scope);
    })
    .catch(err => {
      console.error('Registration failed:', err);
    });
  });
}

أعِد تحميل المتصفّح. لاحظ أن وحدة التحكم تعرض نطاق مشغّل الخدمات (في هذه الحالة http://localhost:8081/).

الشرح

يتم التعامل مع الكائن المتوقع من خلال register() إلى كائن التسجيل، الذي يحتوي على نطاق مشغّل الخدمات.

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

نقل مشغّل الخدمات

نقل service-worker.js إلى الدليل below/ وتعديل عنوان URL لعامل الخدمة في رمز التسجيل في index.html.

ألغِ تسجيل مشغّل الخدمات الحالي في المتصفح وأعِد تحميل الصفحة.

تشير وحدة التحكّم إلى أن نطاق مشغّل الخدمات أصبح الآن http://localhost:8081/below/. في متصفِّح Chrome، يمكنك أيضًا الاطّلاع على نطاق مشغّل الخدمات في علامة التبويب "التطبيق" في "أدوات مطوّري البرامج":

في الصفحة الرئيسية، انقر على صفحة أخرى وصفحة أخرى ورجوع. ما طلبات الجلب التي يتم تسجيلها؟ أي منها ليس؟

الشرح

النطاق التلقائي لعامل الخدمة هو المسار إلى ملف مشغّل الخدمات. بما أن ملف مشغّل الخدمات يقع الآن في below/، هذا هو نطاقه. لا تسجِّل وحدة التحكُّم الآن سوى أحداث جلب البيانات للنطاق another.html وanother.css وanother.js، لأن هذه هي الموارد الوحيدة ضمن نطاق مشغّل الخدمات.

ضبط نطاق عشوائي

انقِل مشغّل الخدمات مرة أخرى إلى الدليل الجذري للمشروع (app/) وعدِّل عنوان URL لعامل الخدمة في رمز التسجيل على index.html.

استخدِم المرجع على MDN لضبط نطاق مشغّل الخدمات على الدليل below/ باستخدام المعلّمة الاختيارية في register().

ألغِ تسجيل مشغّل الخدمات وأعِد تحميل الصفحة. انقر على صفحة أخرى وصفحة أخرى ورجوع.

تُظهر وحدة التحكُّم مرة أخرى أن نطاق مشغّل الخدمات أصبح الآن http://localhost:8081/below/، ولا يجلب السجلّات أحداث سوى another.html وanother.css وanother.js.

الشرح

من الممكن ضبط نطاق عشوائي من خلال إدخال معلمة إضافية عند التسجيل، على سبيل المثال:

navigator.serviceWorker.register('/service-worker.js', {
  scope: '/kitten/'
});

في المثال أعلاه، تم ضبط نطاق مشغّل الخدمات على /kitten/. يعترض مشغّل الخدمات الطلبات من صفحات في /kitten/ و/kitten/lower/ وليس من صفحات مثل /kitten أو /.

ملاحظة: لا يمكنك ضبط نطاق عشوائي تتجاوز الموقع الجغرافي الفعلي لعامل الخدمة. ومع ذلك، إذا كان مشغّل الخادم نشطًا على برنامج يتم عرضه مع العنوان Service-Worker-Allowed، يمكنك تحديد نطاق أقصى لعامل الخدمة هذا فوق موقع مشغّل الخدمات.

للحصول على معلومات إضافية

رمز الحلّ

للحصول على نسخة من رمز العمل، انتقل إلى مجلد solution/.

لديك الآن مشغّل خدمات بسيط يعمل ويشغّل دورة حياة مشغّل الخدمات.

للحصول على معلومات إضافية

دورة حياة مشغّل الخدمات

للاطّلاع على جميع الدروس التطبيقية حول الترميز في الدورة التدريبية لتطبيق الويب التقدّمي (PWA)، راجِع الدرس التطبيقي حول الترميز الترحيبي للدورة التدريبية/