وحدات ES في مشغّلي الخدمات

بديل حديث لواجهة برمجة التطبيقات importScripts()‎

الخلفية

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

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

حالات الاستخدام

إنّ حالة الاستخدام المثالية لمكوّنات ES داخل مهام الخدمة هي لتحميل مكتبة أو رمز إعدادات حديثَين تتم مشاركتهما مع أوقات التشغيل الأخرى التي تتوافق مع مكوّنات ES.

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

يمكن للنصوص البرمجية التي تم استيرادها من خلال وحدات ES بدء عملية التحديث للعامل الخدمي في حال تغيّر محتواها، ما يتطابق مع السلوك importScripts().

القيود الحالية

عمليات الاستيراد الثابتة فقط

يمكن استيراد وحدات ES بطريقتَين: إما بشكل ثابت، باستخدام بنية import ... from '...'، أو بشكل ديناميكي، باستخدام الطريقة import(). داخل عامل الخدمة، لا تتوفّر حاليًا سوى البنية static.

هذا التقييد مشابه لمحاولة فرض قيود مماثلة على استخدام importScripts(). لا تعمل طلبات importScripts() الديناميكية داخل عامل الخدمة، ويجب إكمال جميع طلبات importScripts() التي تتم بشكلٍ متزامن بشكلٍ أساسي قبل أن يكمل عامل الخدمة مرحلة install. يضمن هذا القيد أنّ المتصفّح يعرف كل رمز JavaScript المطلوب لتنفيذ worker الخدمة أثناء التثبيت، ويكون قادرًا على تخزينه مؤقتًا بشكل ضمني.

في نهاية المطاف، قد يتم رفع هذا القيد، وقد يُسمح باستيراد وحدات ES الديناميكية. في الوقت الحالي، تأكَّد من استخدام البنية الثابتة فقط داخل عامل خدمة.

ماذا عن العمال الآخرين؟

إنّ استخدام وحدات ES في "العمال المخصّصين"، أي تلك المُنشأة باستخدام new Worker('...', {type: 'module'})، هو أكثر انتشارًا، وقد أصبح متاحًا في Chrome وEdge منذ الإصدار 80، بالإضافة إلى الإصدارات الحديثة من Safari. يمكن استيراد كلّ من وحدات ES الثابتة والديناميكية في "العمال المخصّصين".

يتيح Chrome وEdge استخدام وحدات ES في الوظائف المشترَكة منذ الإصدار 83، ولكن لا يتيح أي متصفّح آخر استخدامها في الوقت الحالي.

لا تتوفّر إمكانية استيراد الخرائط

تسمح خرائط الاستيراد لشدَّود التشغيل بإعادة كتابة محدّدات الوحدات، على سبيل المثال، لإضافة عنوان URL لشبكة توصيل المحتوى (CDN) المفضّلة التي يمكن من خلالها تحميل وحدات ES.

على الرغم من أنّ Chrome وEdge الإصدار 89 والإصدارات الأحدث يتوافقان مع استيراد الخرائط، فإنه لا يمكن استخدامهما حاليًا مع عمال الخدمة.

دعم المتصفح

تتوفّر وحدات ES في مهام الخدمة في Chrome وEdge اعتبارًا من الإصدار 91.

أضاف Safari هذه الميزة في الإصدار 122 من Technology Preview، ومن المفترض أن يطرح المطوّرون هذه الوظيفة في الإصدار الثابت من Safari في المستقبل.

مثال على الرمز

في ما يلي مثال أساسي لاستخدام وحدة ES مشترَكة في window سياق تطبيق ويب، مع تسجيل عامل خدمة يستخدم وحدة ES نفسها أيضًا:

// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
  import {cacheName} from './config.js';
  // Do something with cacheName.

  await navigator.serviceWorker.register('es-module-sw.js', {
    type: 'module',
  });
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(cacheName);
    // ...
  })());
});

التوافق مع الإصدارات السابقة

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

لاستيعاب المتصفحات التي لا تتضمّن ميزة مدمجة، يمكنك تشغيل ملف برمجي لعامل الخدمة من خلال أداة تجميع متوافقة مع وحدات ES لإنشاء عامل خدمة يتضمّن كل رمز الوحدة مضمّنًا، وسيعمل في المتصفحات القديمة. بدلاً من ذلك، إذا كانت الوحدات التي تحاول استيرادها متوفرة مجمّعة في تنسيقَي IIFE أو UMD، يمكنك استيرادها باستخدام importScripts().

بعد توفُّر نسختَين من worker الخدمة، إحداهما تستخدِم وحدات ES والأخرى لا تستخدِمها، عليك رصد ما يتوافق مع المتصفّح الحالي وتسجيل نص worker الخدمة المقابل. إنّ أفضل الممارسات لرصد الدعم قيد المراجعة حاليًا، ولكن يمكنك متابعة المناقشة في هذه المشكلة على GitHub للحصول على اقتراحات.

_صورة لفلاديو باونوفيتش على Unsplash_