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

بديل حديث لـ importScripts().

خلفية

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

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

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

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

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

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

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

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

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

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

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

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

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

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

عدم توفّر ميزة "خرائط الاستيراد"

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

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

دعم المتصفح

تتوفّر وحدات 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 في مشغّلي الخدمات، ولكن حتى وقت كتابة هذه المقالة، لم يكن الأمر كذلك.

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

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