دليلك الشامل لإنشاء إضافة جوجل كروم احترافية: تطوير المكونات الإضافية للمتصفح بأحدث التقنيات
قد يبدو تطوير إضافة لمتصفح جوجل كروم مهمة معقدة في البداية، خاصة وأنها تختلف جوهريًا عن بناء تطبيقات الويب التقليدية. ففي عالم الإضافات، يجب أن نكون حذرين للغاية بشأن الحمل الزائد لـ JavaScript على المتصفح، إذ تعمل الإضافة جنبًا إلى جنب مع الموقع الذي يزوره المستخدم. علاوة على ذلك، غالبًا ما نفتقر إلى المزايا المتقدمة للتجميع (bundling) والتصحيح (debugging) التي توفرها أدوات التجميع والأطر الحديثة.
عندما قررتُ الخوض في غمار بناء إضافة لكروم، لاحظتُ ندرة المحتوى المتاح حول هذا الموضوع، وتحديدًا عند الرغبة في استخدام تقنيات حديثة مثل TailwindCSS. في هذا الدليل الشامل، سنستكشف معًا كيفية بناء إضافة كروم متكاملة باستخدام Parcel.js للتجميع والمراقبة الفورية (watching)، و TailwindCSS للتصميم الأنيق. كما سنتطرق إلى كيفية عزل أنماط إضافتك لتجنب أي تعارض مع أنماط المواقع المستهدفة، وهو جانب حيوي سنتعمق فيه لاحقًا.
أنواع إضافات جوجل كروم: فهم الآليات الأساسية
تتعدد أنواع إضافات جوجل كروم، وكل نوع يخدم غرضًا محددًا. إليك أبرزها:
Content Scripts(سكريبتات المحتوى): تُعد الأكثر شيوعًا. تعمل هذه السكريبتات ضمن سياق صفحة الويب التي يزورها المستخدم، مما يتيح لها تعديل محتواها وتفاعلاتها. هذا هو النوع الذي سنركز عليه في دليلنا هذا.Popup(النوافذ المنبثقة): تعتمد هذه الإضافات على أيقونة الإضافة الموجودة على يمين شريط العنوان لفتح نافذة منبثقة. يمكن لهذه النافذة أن تحتوي على أي محتوىHTMLمرغوب فيه، مما يوفر واجهة تفاعلية سريعة للمستخدم.Options UI(واجهة خيارات المستخدم): كما يوحي اسمها، توفر هذه الواجهة إمكانية تخصيص خيارات الإضافة. يمكن الوصول إليها بالنقر بزر الفأرة الأيمن على أيقونة الإضافة واختيار “الخيارات” (options)، أو من خلال صفحة الإضافات في كروم عبر الرابطchrome://extensions.DevTools Extension(إضافات أدوات المطور): وفقًا لوثائق جوجل كروم، “تضيف إضافة أدوات المطور وظائف جديدة إلى أدوات مطوري كروم (Chrome DevTools). يمكنها إضافة لوحات وشرائط جانبية جديدة لواجهة المستخدم، التفاعل مع الصفحة المفحوصة، الحصول على معلومات حول طلبات الشبكة، والمزيد”.
في هذا الدليل، سنقوم ببناء إضافة كروم تركز بشكل كامل على Content Scripts، حيث سنعرض المحتوى مباشرة على صفحة الويب ونتفاعل مع نموذج كائن المستند (DOM).
تجميع إضافة كروم باستخدام Parcel.js V2: البداية السريعة
يُعد Parcel.js مجمعًا لتطبيقات الويب يتميز بكونه لا يتطلب أي إعدادات معقدة (zero-configuration). يمكنه استخدام أي نوع من الملفات كنقطة دخول (entry point)، وهو سهل الاستخدام وفعال لمختلف أنواع التطبيقات، بما في ذلك إضافات كروم. لنبدأ بإنشاء مشروعنا:
إنشاء هيكل المشروع الأولي
أولاً، قم بإنشاء مجلد جديد باسم demo-extension. تأكد من تثبيت yarn أو npm على نظامك؛ في هذا الدليل، سنستخدم yarn:
$ mkdir demo-extension && cd demo-extension && yarn init -y
بعد ذلك، سنقوم بتثبيت Parcel كاعتمادية تطوير محلية (local dependency):
$ yarn add -D parcel@next
الآن، أنشئ مجلدًا جديدًا باسم src داخل مجلد المشروع:
$ mkdir src
إضافة ملف البيان (Manifest File): قلب الإضافة
كل إضافة متصفح تتطلب ملف بيان (manifest file). هذا الملف هو بمثابة الهوية والتعليمات الأساسية للإضافة، حيث نحدد فيه الإصدار (version) والبيانات الوصفية (meta data) الخاصة بها، بالإضافة إلى السكريبتات المستخدمة (مثل content، background، popup، إلخ) وأي صلاحيات (permissions) تحتاجها الإضافة. يمكنك العثور على المخطط الكامل لملف البيان في وثائق كروم الرسمية: https://developer.chrome.com/extensions/manifest
لنقم بإنشاء ملف جديد باسم manifest.json داخل مجلد src بالمحتوى التالي:
{ "name" : "Demo extension" , "description" : "An extension built with Parcel and TailwindCSS." , "version" : "1.0" , "manifest_version" : 2 }
ملاحظة: قبل أن نتعمق في كيفية عمل إضافات كروم والوظائف التي يمكن بناؤها، سنقوم بإعداد TailwindCSS.
دمج TailwindCSS مع إضافة كروم: تصميم مرن وفعال
يُعد TailwindCSS إطار عمل CSS فريدًا يعتمد على فئات مساعدة منخفضة المستوى (utility classes) لإنشاء مكونات واجهة مستخدم مرئية قابلة لإعادة الاستخدام والتخصيص في آن واحد. يمكن تثبيت Tailwind بطريقتين، لكن الطريقة الأكثر شيوعًا هي عبر حزمة NPM الخاصة به:
تثبيت TailwindCSS والتبعيات
قم بتثبيت TailwindCSS باستخدام الأمر التالي:
$ yarn add tailwindcss
بالإضافة إلى ذلك، ستحتاج إلى تثبيت autoprefixer و postcss-import كاعتماديات تطوير:
$ yarn add -D autoprefixer postcss-import
تُستخدم هذه الحزم لإضافة البادئات الخاصة بالمتصفحات (vendor prefixes) إلى أنماط CSS الخاصة بك، ولتمكينك من استيراد ملفات Tailwind مباشرة من مجلد node_modules باستخدام صيغ مثل @import "tailwindcss/base".
إعداد PostCSS
بعد التثبيت، أنشئ ملفًا جديدًا في المجلد الجذري لمشروعك وسمّه postcss.config.js. هذا هو ملف إعداد PostCSS، وسيحتوي في الوقت الحالي على الأسطر التالية:
module.exports = { plugins: [ require("postcss-import"), require("tailwindcss"), require("autoprefixer"), ],};
ملاحظة هامة: ترتيب المكونات الإضافية (plugins) هنا له أهمية قصوى!
هذا كل ما تحتاجه للبدء في استخدام TailwindCSS ضمن إضافة كروم الخاصة بك. الآن، أنشئ ملفًا باسم style.css داخل مجلد src وقم بتضمين ملفات Tailwind الأساسية فيه:
@import "tailwindcss/base"; @import "tailwindcss/utilities";
تحسين الأداء: إزالة أنماط CSS غير المستخدمة باستخدام PurgeCSS
لضمان أفضل أداء لإضافتنا، يجب أن نتأكد من تضمين الأنماط الضرورية فقط. يمكننا تحقيق ذلك من خلال تفعيل ميزة التنقية (purging) في TailwindCSS. ابدأ بإنشاء ملف إعداد جديد لـ Tailwind عن طريق تشغيل الأمر التالي:
$ npx tailwindcss init
سيؤدي هذا إلى إنشاء ملف جديد باسم tailwind.config.js. لإزالة أنماط CSS غير المستخدمة، سنضيف ملفات المصدر الخاصة بنا إلى حقل purge داخل هذا الملف بالشكل التالي:
module.exports = { purge: [ './src/**/*.js', ], theme: {}, variants: {}, plugins: [],}
بهذه الطريقة، سيتم تنقية CSS الخاص بنا وإزالة الأنماط غير المستخدمة عند بناء الإضافة لبيئة الإنتاج، مما يقلل من حجم الملفات ويحسن سرعة التحميل.
تفعيل التحديث السريع (Hot Reloading) في إضافة كروم
قبل أن نبدأ بإضافة المحتوى الفعلي لإضافتنا، دعنا نُفعّل ميزة التحديث السريع (hot reloading)، وهي ميزة حيوية لسرعة التطوير. فمتصفح كروم لا يقوم بإعادة تحميل ملفات المصدر تلقائيًا عند إجراء التغييرات؛ بل يتطلب منك النقر يدويًا على زر “إعادة التحميل” (Reload) في صفحة الإضافات. لحسن الحظ، توجد حزمة NPM تقوم بهذه المهمة نيابةً عنا:
تثبيت وإعداد crx-hotreload
قم بتثبيت الحزمة باستخدام الأمر التالي:
$ yarn add crx-hotreload
لاستخدامها، سنقوم بإنشاء ملف جديد باسم background.js داخل مجلد src واستيراد crx-hotreload فيه:
import "crx-hotreload";
أخيرًا، يجب أن نشير إلى ملف background.js في ملف manifest.json لكي يتم تضمينه مع إضافتنا (يتم تعطيل التحديث السريع في بيئة الإنتاج افتراضيًا):
{ "name" : "Demo extension" , "description" : "An extension built with Parcel and TailwindCSS." , "version" : "1.0" , "manifest_version" : 2 , "background" : { "scripts" : [ "background.js" ] } }
كفى إعدادات! لننتقل الآن إلى بناء نموذج سكريبت بسيط داخل إضافتنا.
أنواع السكريبتات في إضافات كروم: Content و Background
كما ذكرنا في بداية هذا الدليل، هناك أنواع مختلفة من السكريبتات التي يمكنك استخدامها في إضافات كروم، لكل منها وظيفته وسياقه الخاص:
Content Scripts(سكريبتات المحتوى): هي السكريبتات التي تعمل مباشرة ضمن سياق صفحة الويب التي يزورها المستخدم. تتيح لك هذه السكريبتات تشغيل أي كودJavaScriptمتاح في صفحة الويب العادية، بما في ذلك الوصول إلى نموذج كائن المستند (DOM) والتلاعب به.Background Scripts(سكريبتات الخلفية): على النقيض، تعمل سكريبتات الخلفية بشكل مستقل عن صفحات الويب، وهي المكان الذي يمكنك فيه التفاعل مع أحداث المتصفح المختلفة (مثل فتح علامة تبويب جديدة أو النقر على أيقونة الإضافة). تتمتع هذه السكريبتات بإمكانية الوصول إلى واجهات برمجة تطبيقات (APIs) إضافات كروم، مما يمنحها صلاحيات أوسع للتحكم في المتصفح.
إضافة سكريبت المحتوى (Content Script) وتطبيق Shadow DOM
لنقم بإنشاء ملف جديد باسم content-script.js ضمن مجلد src. في هذا الملف، سنضيف نموذج HTML التالي الذي سيمثل واجهة إضافتنا:
import cssText from "bundle-text:../dist/style.css"; const html = ` <style> ${cssText} </style> <section id="popup" class="font-sans text-black z-50 w-full fixed top-0 right-0 shadow-xl new-event-form bg-white max-w-sm border-2 border-black p-5 rounded-lg border-b-6"> <header class="flex mb-5 pl-1 items-center justify-between"> <span class="text-2xl text-black font-extrabold">New event!</span> </header> <main class="event-name-input mb-6"> <div class="mb-6"> <label for="event-name" class="font-bold pl-1 block mb-1 text-black text-xl" > Event name </label> <div class="duration-400 flex bg-white border-black border-2 rounded-lg py-4 px-4 text-black text-xl focus-within:shadow-outline"> <input id="event-name" name="event-name" type="text" placeholder="web.dev LIVE" class="font-medium w-full focus:outline-none" /> </div> </div> <div class="mb-6"> <label for="event-date" class="font-bold pl-1 block mb-1 text-black text-xl" > Date </label> <div class="event-date-input duration-400 border-black flex bg-white border-2 rounded-lg py-4 px-4 text-xl focus-within:shadow-outline"> <input id="event-date" name="event-date" type="date" class="font-medium w-full focus:outline-none" /> </div> </div> <div class=" mb-8"> <label for="event-time-input" class="font-bold pl-1 block mb-1 text-xl" > Time </label> <div class="inline-flex items-center"> <input id="event-time-input" type="time" value="17:30" class="border-black mr-4 lowercase duration-400 w-auto bg-white text-xl border-2 rounded-lg px-4 py-4 focus:outline-none focus:shadow-outline" /> <div class="inline-flex flex-col"> <span class="text-xl font-bold">Casablanca</span> <span class="text-base font-normal">Africa</span> </div> </div> </main> <footer> <button class="duration-400 bg-green-400 text-xl py-4 w-full rounded-lg border-2 border-b-6 leading-7 font-extrabold border-black focus:outline-none focus:shadow-outline" > Save </button> </footer> </section> `; const shadowHost = document.createElement("div"); document.body.insertAdjacentElement("beforebegin", shadowHost); const shadowRoot = shadowHost.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = html;
قد لا يكون تصميم إضافة المتصفح أمرًا مباشرًا كما تتخيل، لأنك تحتاج إلى التأكد من أن أنماط موقع الويب لا تتأثر بأنماط إضافتك. لعزل هذه الأنماط، سنستخدم تقنية قوية تُعرف باسم Shadow DOM.
فهم Shadow DOM: عزل الأنماط بفعالية
Shadow DOM هي تقنية تغليف قوية للأنماط (encapsulation technique). هذا يعني أن الأنماط تكون محصورة (scoped) ضمن شجرة Shadow، وبالتالي لا تتسرب أي أنماط إلى صفحة الويب التي تتم زيارتها. كما أن الأنماط الخارجية لا تتجاوز محتوى Shadow DOM، على الرغم من أن متغيرات CSS (CSS variables) قد تظل قابلة للوصول.
Shadow Host: هو أي عنصرDOMنرغب في إرفاق شجرةShadowبه.Shadow Root: هو ما يتم إرجاعه من الدالةattachShadow()، ومحتواه هو ما يتم عرضه فعليًا.
تنبيه: الطريقة الوحيدة لتصميم محتوى شجرة Shadow هي عبر تضمين الأنماط مباشرة (inlining styles).
يحتوي Parcel V2 على ميزة مدمجة جديدة تسمح لك باستيراد محتوى حزمة (bundle) واستخدامه كنص مجمّع داخل ملفات JavaScript الخاصة بك. سيقوم Parcel بعد ذلك باستبدال هذا المحتوى وقت التغليف. لقد طبقنا هذا بالضبط مع حزمة style.css الخاصة بنا. الآن يمكننا تضمين CSS تلقائيًا في Shadow DOM وقت البناء.
تحديث ملف البيان (manifest.json)
الآن علينا إخبار المتصفح بهذا الملف الجديد. لنقم بتضمينه عن طريق إضافة هذه الأسطر إلى ملف manifest.json الخاص بنا:
{ "name" : "Demo extension" , "description" : "An extension built with Parcel and TailwindCSS." , "version" : "1.0" , "manifest_version" : 2 , "background" : { "scripts" : [ "background.js" ] }, "content_scripts" : [ { "matches" : [ "<all_urls>" ], "js" : [ "content-script.js" ] } ] }
تشغيل الإضافة واختبارها محليًا
لتشغيل إضافتنا، سنضيف بعض الأوامر (scripts) إلى ملف package.json الخاص بنا:
{ "scripts" : { "prebuild" : "rm -rf dist .cache .parcel-cache" , "build:tailwind" : "tailwindcss build src/style.css -c ./tailwind.config.js -o dist/style.css" , "watch" : "NODE_ENV=development yarn build:tailwind && cp src/manifest.json dist/ && parcel watch --no-hmr src/{background.js,content-script.js}" , "build" : "NODE_ENV=production yarn build:tailwind && cp src/manifest.json dist/ && parcel build src/{background.js,content-script.js}" } }
أخيرًا، يمكنك تشغيل الأمر yarn watch. بعد ذلك، انتقل إلى صفحة إضافات كروم في متصفحك عن طريق كتابة chrome://extensions في شريط العنوان. تأكد من تفعيل “وضع المطور” (Developer Mode) في الزاوية العلوية اليمنى من الصفحة. انقر على “تحميل إضافة غير مجمعة” (Load Unpacked) واختر مجلد dist الموجود داخل مجلد demo-extension.
إذا واجهت الخطأ التالي: Error: Bundles must have unique filePaths، يمكنك إصلاحه ببساطة عن طريق إزالة الحقل main من ملف package.json الخاص بك.
نشر إضافتك على متجر كروم الإلكتروني
قبل المضي قدمًا في عملية النشر، دعنا نضف أمر NPM script جديدًا سيساعدنا في ضغط ملفات الإضافة بالشكل المطلوب من قبل متجر كروم الإلكتروني.
إضافة أمر الضغط (zip)
قم بتعديل قسم scripts في ملف package.json ليصبح كالتالي:
{ "scripts" : { "prebuild" : "rm -rf dist .cache" , "build:tailwind" : "tailwindcss build src/style.css -c ./tailwind.config.js -o dist/style.css" , "watch" : "NODE_ENV=development yarn build:tailwind && cp src/manifest.json dist/ && parcel watch --no-hmr src/{background.js,content-script.js}" , "build" : "NODE_ENV=production yarn build:tailwind && cp src/manifest.json dist/ && parcel build src/{background.js,content-script.js}" , "zip" : "zip -r chrome-extension.zip ./dist" } }
إذا لم تكن قد قمت بتثبيت أداة zip بعد، يرجى القيام بذلك:
- لنظام
MacOS:brew install zip - لنظام
Linux:sudo apt install zip - لنظام
Windows: يمكنك استخدام أمرpowershell Compress-Archiveالمشابه:powershell Compress-Archive -Path .\dist\ -Destination .\chrome-extension.zip
الآن، كل ما عليك فعله هو التوجه إلى لوحة تحكم مطوري متجر كروم الإلكتروني لإعداد حسابك ونشر إضافتك! يمكنك العثور على النسخة التجريبية الكاملة لهذا الدليل على حسابي في GitHub.
الخلاصة التقنية
في الختام، وعلى الرغم من بعض الفروقات الجوهرية، فإن إضافات كروم ليست بعيدة كل البعد عن تطبيقات الويب التقليدية من حيث مبادئ التطوير. لقد تعلمت اليوم كيفية بناء إضافة متكاملة باستخدام أحدث التقنيات والممارسات في عالم تطوير الويب، مثل Parcel.js للتجميع الفعال، و TailwindCSS للتصميم المرن، و Shadow DOM لعزل الأنماط وضمان التوافقية. نأمل أن يكون هذا الدليل قد ساعدك في تسريع عملية تطوير إضافاتك الخاصة، وفتح لك آفاقًا جديدة للإبداع في بيئة المتصفح.