دليل تعليمي يتناول مفاهيم "عامل الخدمة" لإضافة الخدمة
نظرة عامة
تقدّم هذه المقالة التعليمية مقدّمة عن مهام الخدمة في إضافات Chrome. كجزء من هذا الدليل التمهيدي، ستنشئ إضافة تتيح للمستخدمين الانتقال بسرعة إلى صفحات مرجع واجهة برمجة التطبيقات Chrome API باستخدام مربّع البحث الشامل. ستتعرّف على كيفية:
- سجِّل مشغّل الخدمات وأدخِل الوحدات.
- تصحيح أخطاء عامل خدمة الإضافة
- إدارة الحالة ومعالجة الأحداث
- بدء أحداث دورية
- التواصل مع النصوص البرمجية للمحتوى
قبل البدء
يفترض هذا الدليل أنّ لديك خبرة أساسية في تطوير الويب. ننصحك بمراجعة الدليل الأساسي للإضافة ومرحبًا بك للحصول على مقدمة عن تطوير الإضافات.
إنشاء الإضافة
ابدأ بإنشاء دليل جديد باسم quick-api-reference
لتخزين ملفات الإضافات، أو
نزِّل رمز المصدر من مستودع عيّنات GitHub.
الخطوة 1: تسجيل الخدمة العاملة
أنشئ ملف manifest في جذر المشروع وأضِف الرمز البرمجي التالي:
manifest.json:
{
"manifest_version": 3,
"name": "Open extension API reference",
"version": "1.0.0",
"icons": {
"16": "images/icon-16.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "service-worker.js"
}
}
تسجِّل الإضافات عامل الخدمة في البيان الذي لا يستخدِم سوى ملف JavaScript واحد.
لا حاجة إلى طلب navigator.serviceWorker.register()
، كما تفعل في صفحة ويب.
أنشئ مجلدًا باسم images
ثم نزِّل الرموز إليه.
اطّلِع على الخطوات الأولى من الدليل التعليمي "وقت القراءة" للتعرّف على مزيد من المعلومات حول metadata والرموز في البيان الخاص باإضافة.
الخطوة 2: استيراد وحدات مهام الخدمة المتعدّدة
ينفِّذ عامل الخدمة لدينا ميزتَين. لتحسين قابلية الصيانة، سننفّذ كل ميزة في وحدة منفصلة. أولاً، علينا تحديد الخدمة العاملة على أنّها وحدة ES في البيان، ما يسمح لنا باستيراد الوحدات في الخدمة العاملة:
manifest.json:
{
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
}
أنشئ ملف service-worker.js
واستورِد وحدتَين:
import './sw-omnibox.js';
import './sw-tips.js';
أنشئ هذه الملفات وأضِف سجلّ وحدة تحكّم إلى كل ملف.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
اطّلِع على استيراد النصوص البرمجية للتعرّف على طرق أخرى لاستيراد ملفات متعددة في عامل خدمة.
اختياري: تصحيح أخطاء الخدمة العاملة
سأشرح كيفية العثور على سجلات عامل الخدمة ومعرفة وقت إنهائه. أولاً، اتّبِع التعليمات لتحميل إضافة غير مُعبَّأة.
بعد 30 ثانية، ستظهر لك رسالة "عامل الخدمة (غير نشط)"، ما يعني أنّ عامل الخدمة قد تم إنهاءه. انقر على الرابط "عامل الخدمة (غير نشط)" لفحصه. توضِّح الصورة المتحركة التالية ذلك.
هل لاحظت أنّ فحص مشغّل الخدمة قد أيقظه؟ سيؤدي فتح الخدمة العاملة في أدوات المطوّر إلى إبقائها نشطة. للتأكّد من أنّ الإضافة تعمل بشكل صحيح عند إنهاء الخدمة، احرص على إغلاق "أدوات المطوّر".
الآن، يمكنك تقسيم الإضافة لمعرفة مكان تحديد الأخطاء. وتتمثّل إحدى الطرق لإجراء ذلك في حذف ".js" من عملية استيراد './sw-omnibox.js'
في ملف service-worker.js
. لن يتمكّن Chrome من تسجيل مشغّل الخدمة.
ارجع إلى chrome://extensions وأعِد تحميل الإضافة. ستظهر لك خطأان:
Service worker registration failed. Status code: 3.
An unknown error occurred when fetching the script.
اطّلِع على تصحيح أخطاء الإضافات للتعرّف على المزيد من الطرق لتصحيح أخطاء عامل الخدمة في الإضافة.
الخطوة 4: بدء الحالة
سيوقف Chrome خدمات "العمال في الخدمة" إذا لم تكن مطلوبة. نستخدم واجهة برمجة التطبيقات chrome.storage
للحفاظ على الحالة في جميع جلسات الخدمة العاملة. للوصول إلى مساحة التخزين، يجب طلب الإذن في البيان:
manifest.json:
{
...
"permissions": ["storage"],
}
أولاً، عليك حفظ الاقتراحات التلقائية في مساحة التخزين. يمكننا بدء الحالة عند تثبيت الإضافة لأول مرة من خلال الاستماع إلى حدث runtime.onInstalled()
:
sw-omnibox.js:
...
// Save default API suggestions
chrome.runtime.onInstalled.addListener(({ reason }) => {
if (reason === 'install') {
chrome.storage.local.set({
apiSuggestions: ['tabs', 'storage', 'scripting']
});
}
});
لا يمكن لعمال الخدمة الوصول مباشرةً إلى عنصر النافذة، وبالتالي لا يمكنهم استخدام
window.localStorage
لتخزين القيم. بالإضافة إلى ذلك، وحدات الخدمة هي بيئات تنفيذ قصيرة الأجل، ويُنهى تشغيلها بشكل متكرّر خلال جلسة المتصفّح للمستخدم، ما يجعلها غير متوافقة مع المتغيّرات الكلية. بدلاً من ذلك، استخدِم chrome.storage.local
الذي يخزِّن البيانات على الجهاز المحلي.
اطّلِع على تخزين البيانات بدلاً من استخدام المتغيّرات الشاملة للتعرّف على خيارات التخزين الأخرى لعمال خدمات الإضافات.
الخطوة 5: تسجيل أحداثك
يجب تسجيل جميع مستمعي الأحداث بشكل ثابت في النطاق العام لخدمة Worker. بعبارة أخرى، يجب عدم تداخل معالجات الأحداث في الدوال غير المتزامنة. بهذه الطريقة، يمكن لمتصفّح Chrome ضمان استعادة جميع معالجات الأحداث في حال إعادة تشغيل عامل الخدمة.
في هذا المثال، سنستخدم واجهة برمجة التطبيقات chrome.omnibox
، ولكن علينا أولاً الإفصاح عن عامل تشغيل الكلمات الرئيسية في مربّع البحث الشامل في البيان:
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
الآن، سجِّل أدوات معالجة أحداث مربّع البحث الشامل في أعلى مستوى من النص البرمجي. عندما يُدخِل المستخدم الكلمة الرئيسية للمربّع المتعدّد الاستخدامات (api
) في شريط العناوين متبوعة بعلامة تبويب أو مسافة، سيعرض Chrome قائمة بالاقتراحات استنادًا إلى الكلمات الرئيسية في مساحة التخزين. إنّ الحدث onInputChanged()
الذي يأخذ إدخال المستخدم الحالي وعنصر suggestResult
هو المسؤول عن تعبئة هذه الاقتراحات.
sw-omnibox.js:
...
const URL_CHROME_EXTENSIONS_DOC =
'https://developer.chrome.com/docs/extensions/reference/';
const NUMBER_OF_PREVIOUS_SEARCHES = 4;
// Display the suggestions after user starts typing
chrome.omnibox.onInputChanged.addListener(async (input, suggest) => {
await chrome.omnibox.setDefaultSuggestion({
description: 'Enter a Chrome API or choose from past searches'
});
const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');
const suggestions = apiSuggestions.map((api) => {
return { content: api, description: `Open chrome.${api} API` };
});
suggest(suggestions);
});
بعد اختيار المستخدم اقتراحًا، سيفتح onInputEntered()
صفحة مرجع Chrome API المقابلة.
sw-omnibox.js:
...
// Open the reference page of the chosen API
chrome.omnibox.onInputEntered.addListener((input) => {
chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });
// Save the latest keyword
updateHistory(input);
});
تأخذ الدالة updateHistory()
مدخل المربع المتعدّد الاستخدامات وتحفظه في storage.local
. بهذه الطريقة، يمكن استخدام أحدث عبارة بحث لاحقًا كاقتراح في المربّع المتعدد الاستخدامات.
sw-omnibox.js:
...
async function updateHistory(input) {
const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');
apiSuggestions.unshift(input);
apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);
return chrome.storage.local.set({ apiSuggestions });
}
الخطوة 6: إعداد حدث متكرّر
تُستخدَم الطريقتان setTimeout()
أو setInterval()
عادةً لتنفيذ المهام
المتأخرة أو الدورية. ومع ذلك، يمكن أن تتعذّر هذه واجهات برمجة التطبيقات لأنّ أداة جدولة المهام ستلغي الموقّتات عند إنهاء الخدمة
العملية. بدلاً من ذلك، يمكن للإضافات استخدام واجهة برمجة التطبيقات chrome.alarms
.
ابدأ بطلب إذن "alarms"
في البيان. بالإضافة إلى ذلك، لجلب نصائح الإضافات من موقع مستضاف عن بُعد، عليك طلب إذن المضيف:
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
"host_permissions": ["https://chrome.dev/f/*"],
}
ستسترجع الإضافة جميع النصائح، وستختار نصيحة واحدة عشوائيًا وتحفظها في مساحة التخزين. سننشئ منبّهًا يتم تشغيله مرة واحدة في اليوم لتعديل النصيحة. لا يتم حفظ الإنذارات عند إغلاق Chrome. لذلك، علينا التحقّق مما إذا كان المنبّه متوفّرًا وإنشاؤه إذا لم يكن كذلك.
sw-tips.js:
// Fetch tip & save in storage
const updateTip = async () => {
const response = await fetch('https://chrome.dev/f/extension_tips');
const tips = await response.json();
const randomIndex = Math.floor(Math.random() * tips.length);
return chrome.storage.local.set({ tip: tips[randomIndex] });
};
const ALARM_NAME = 'tip';
// Check if alarm exists to avoid resetting the timer.
// The alarm might be removed when the browser session restarts.
async function createAlarm() {
const alarm = await chrome.alarms.get(ALARM_NAME);
if (typeof alarm === 'undefined') {
chrome.alarms.create(ALARM_NAME, {
delayInMinutes: 1,
periodInMinutes: 1440
});
updateTip();
}
}
createAlarm();
// Update tip once a day
chrome.alarms.onAlarm.addListener(updateTip);
الخطوة 7: التواصل مع السياقات الأخرى
تستخدِم الإضافات نصوص برمجية للمحتوى لقراءة محتوى الصفحة وتعديله. عندما يزور مستخدم صفحة مرجعية لواجهة برمجة التطبيقات Chrome API، سيعدّل نص محتوى الإضافة الصفحة بعرض نصيحة اليوم. يُرسِل رسالة لطلب معلومات عن الإكرامية لهذا اليوم من عامل الخدمة.
ابدأ بتعريف نص المحتوى في البيان وأضِف نمط المطابقة المقابل للمستندات المرجعية لواجهة برمجة التطبيقات Chrome API.
manifest.json:
{
...
"content_scripts": [
{
"matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
"js": ["content.js"]
}
]
}
أنشئ ملف محتوى جديدًا. يُرسِل الرمز التالي رسالة إلى عامل الخدمة يطلب فيها معلومات عن الإكرامية. بعد ذلك، تتم إضافة زر يفتح نافذة منبثقة تحتوي على نصيحة حول الإضافة. يستخدم هذا الرمز البرمجي منصة الويب الجديدة Popover API.
content.js:
(async () => {
// Sends a message to the service worker and receives a tip in response
const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' });
const nav = document.querySelector('.upper-tabs > nav');
const tipWidget = createDomElement(`
<button type="button" popovertarget="tip-popover" popovertargetaction="show" style="padding: 0 12px; height: 36px;">
<span style="display: block; font: var(--devsite-link-font,500 14px/20px var(--devsite-primary-font-family));">Tip</span>
</button>
`);
const popover = createDomElement(
`<div id='tip-popover' popover style="margin: auto;">${tip}</div>`
);
document.body.append(popover);
nav.append(tipWidget);
})();
function createDomElement(html) {
const dom = new DOMParser().parseFromString(html, 'text/html');
return dom.body.firstElementChild;
}
الخطوة الأخيرة هي إضافة معالِج رسائل إلى الخدمة العاملة التي تُرسِل ردًا على نص المحتوى يتضمّن النصيحة اليومية.
sw-tips.js:
...
// Send tip to content script via messaging
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.greeting === 'tip') {
chrome.storage.local.get('tip').then(sendResponse);
return true;
}
});
اختبار صلاحية الإعدادات
تأكَّد من أنّ بنية ملف مشروعك تظهر على النحو التالي:
تحميل الإضافة على الجهاز
لتحميل إضافة غير مضغوطة في وضع المطوّر، اتّبِع الخطوات الواردة في مرحبًا بك.
فتح صفحة مرجعية
- أدخِل الكلمة الرئيسية "api" في شريط عناوين المتصفّح.
- اضغط على مفتاح التبويب (Tab) أو مفتاح المسافة (Space).
- أدخِل الاسم الكامل لواجهة برمجة التطبيقات.
- أو الاختيار من قائمة بعمليات البحث السابقة
- ستفتح صفحة جديدة تنقل إلى صفحة مرجع Chrome API.
من المفترض أن يظهر الرمز على النحو التالي:

فتح نصيحة اليوم
انقر على زر "ملاحظة" في شريط التنقّل لفتح ملاحظة الإضافة.

🎯 التحسينات المحتملة
استنادًا إلى ما تعلمته اليوم، حاوِل تنفيذ أيّ من الإجراءات التالية:
- تعرَّف على طريقة أخرى لتنفيذ اقتراحات مربّع البحث الشامل.
- أنشئ نافذة منبثقة مخصّصة لعرض نصيحة الإضافة.
- افتح صفحة إضافية إلى صفحات واجهة برمجة التطبيقات المرجعية في Web Extensions من MDN.
طاب يومك.
تهانينا على إكمال هذا الدليل التعليمي 🎉. يمكنك مواصلة تطوير مهاراتك من خلال إكمال دروس تعليمية أخرى موجّهة للمبتدئين:
الإضافة | ما ستتعرّف عليه |
---|---|
وقت القراءة | لإدراج عنصر في مجموعة معيّنة من الصفحات تلقائيًا |
مدير علامات التبويب | لإنشاء نافذة منبثقة تدير علامات التبويب في المتصفّح |
وضع التركيز | لتشغيل الرمز على الصفحة الحالية بعد النقر على إجراء الإضافة. |
الاطّلاع على معلومات إضافية
لمواصلة مسار التعلّم الخاص بعامل خدمة التوسيع، ننصحك باستكشاف المقالات التالية: