تتناول هذه المقالة ميزة CSS-in-JS المتوفّرة في أدوات المطوّرين منذ الإصدار 85 من Chrome، وتوضّح بشكل عام ما نقصد به بميزة CSS-in-JS ومدى اختلافها عن ميزة CSS العادية التي كانت أدوات المطوّرين تتيحها منذ فترة طويلة.
ما هو CSS-in-JS؟
تعريف CSS-in-JS غامض إلى حدٍ ما. بشكل عام، هو أسلوب لإدارة رمز CSS باستخدام JavaScript. على سبيل المثال، قد يعني ذلك أنّه تم تحديد محتوى CSS باستخدام JavaScript وأنّ التطبيق ينشئ الإخراج النهائي لملف CSS أثناء التشغيل.
في سياق "أدوات المطوّرين"، تعني ميزة CSS-in-JS أنّه يتمّ إدخال محتوى CSS في الصفحة باستخدام واجهات برمجة تطبيقات CSSOM. يتمّ حقن ملف CSS العادي باستخدام عنصرَي <style>
أو <link>
، ويكون له مصدر ثابت (مثل عقدة DOM أو مورد شبكة). في المقابل، لا يكون لملفات CSS-in-JS مصدر ثابت في أغلب الأحيان. هناك حالة خاصة هنا وهي أنّه يمكن تعديل محتوى عنصر <style>
باستخدام CSSOM API، ما يؤدي إلى عدم مزامنة المصدر مع ورقة أنماط CSS الفعلية.
إذا كنت تستخدم أي مكتبة من مكتبات CSS-in-JS (مثل styled-component وEmotion وJSS)، قد تُدخل المكتبة الأنماط باستخدام واجهات برمجة التطبيقات CSSOM من وراء الكواليس استنادًا إلى وضع التطوير والمتصفّح.
لنلقِ نظرة على بعض الأمثلة على كيفية إدراج جدول أسلوب باستخدام CSSOM API على غرار ما تفعله مكتبات CSS-in-JS.
// Insert new rule to an existing CSS stylesheet
const element = document.querySelector('style');
const stylesheet = element.sheet;
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');
يمكنك أيضًا إنشاء جدول أسلوب جديد تمامًا:
// Create a completely new stylesheet
const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');
// Apply constructed stylesheet to the document
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
إتاحة CSS في "أدوات مطوّري البرامج"
في "أدوات مطوّري البرامج"، تكون لوحة الأنماط هي الميزة الأكثر استخدامًا عند التعامل مع CSS. في لوحة الأنماط، يمكنك الاطّلاع على القواعد التي تنطبق على عنصر معيّن وتعديل القواعد والاطّلاع على التغييرات على الصفحة في الوقت الفعلي.
قبل العام الماضي، كان دعم قواعد CSS المعدَّلة باستخدام واجهات برمجة تطبيقات CSSOM محدودًا إلى حدٍ ما: إذ كان بإمكانك الاطّلاع على القواعد المطبَّقة فقط ولكن لا يمكنك تعديلها. كان الهدف الرئيسي الذي سعينا لتحقيقه العام الماضي هو السماح بتعديل قواعد CSS-in-JS باستخدام لوحة "الأنماط". نشير أحيانًا أيضًا إلى أنماط CSS-in-JS على أنّها "مُنشأة" للإشارة إلى أنّها تم إنشاؤها باستخدام واجهات برمجة تطبيقات الويب.
لنطّلِع على تفاصيل تعديل الأنماط في أدوات مطوّري البرامج.
آلية تعديل الأنماط في "أدوات مطوّري البرامج"
عند اختيار عنصر في DevTools، يتم عرض لوحة الأنماط. تُصدر لوحة الأنماط أمرًا في إطار عمل CDP يُسمى CSS.getMatchedStylesForNode للحصول على قواعد CSS التي تنطبق على العنصر. اختصار CDP يعني Chrome DevTools Protocol، وهو واجهة برمجة تطبيقات تسمح لواجهة "أدوات مطوري البرامج" بالحصول على معلومات إضافية عن الصفحة التي يتم فحصها.
عند الاستدعاء، يحدِّد CSS.getMatchedStylesForNode
جميع أوراق الأنماط في المستند ويحلّلها باستخدام محلِّل CSS في المتصفّح. بعد ذلك، يتم إنشاء فهرس يربط كل قاعدة CSS بموضع في مصدر جدول الأنماط.
قد تتساءل، لماذا يجب تحليل ملف CSS مرة أخرى؟ تكمن المشكلة هنا في أنّ المتصفح نفسه لا يهتم بمواقع مصادر قواعد CSS لأسباب تتعلّق بالأداء، وبالتالي لا يخزنها. ولكن تحتاج أدوات المطوّرين إلى مواضع المصادر لتتمكّن من تعديل CSS. لا نريد أن يدفع مستخدمو Chrome العاديون غرامة الأداء، ولكننا نريد أن يتمكّن مستخدمو "أدوات مطوّري البرامج في Chrome" من الوصول إلى مواضع المصدر. يعالج أسلوب إعادة التحليل هذا كلتا الحالتَين مع الحد الأدنى من الجوانب السلبية.
بعد ذلك، يطلب تنفيذ CSS.getMatchedStylesForNode
من محرّك الأنماط في المتصفّح تقديم قواعد CSS تتطابق مع العنصر المحدّد. وفي النهاية، تربط الطريقة القواعد التي يعرضها محرّك الأنماط برمز المصدر، وتقدّم استجابة منظَّمة عن قواعد CSS حتى تعرف "أدوات المطوّرين" أي جزء من القاعدة هو المحدّد أو السمات. ويسمح ذلك لأدوات المطوّرين بتعديل المحدّد والسمات بشكل مستقل.
لنلقِ الآن نظرة على التعديل. هل تذكُّر أنّ CSS.getMatchedStylesForNode
يعرض مواضع المصدر لكل قاعدة؟ وهذا أمر مهم للتعديل. عند تغيير إحدى القواعد، تُصدر أدوات مطوّري البرامج أمرًا آخر من CDP يؤدي إلى تعديل الصفحة. يتضمّن الأمر الموضع الأصلي للجزء من القاعدة الذي يتم تعديله والنص الجديد الذي يجب تعديل الجزء به.
في الخلفية، عند معالجة طلب التعديل، تعدِّل أدوات مطوري البرامج جدول الأنماط المستهدَف. ويُعدِّل أيضًا نسخة مصدر ملف الأنماط الذي يحتفظ به ويُعدِّل مواضع المصدر للقاعدة المعدَّلة. استجابةً لطلب التعديل، تتلقّى واجهة أدوات المطوّرين المواقف المعدَّلة لجزء النص الذي تم تعديله للتو.
يوضّح ذلك سبب عدم عمل ميزة تعديل CSS-in-JS في "أدوات المطوّر" بشكلٍ تلقائي: لا يتوفّر مصدر فعلي لـ CSS-in-JS يتم تخزينه في أي مكان وتتم تخزين قواعد CSS في ذاكرة المتصفّح ضمن هياكل بيانات CSSOM.
كيفية إضافة ميزة CSS-in-JS
لذلك، لدعم تعديل قواعد CSS-in-JS، قرّرنا أنّ أفضل حلّ هو إنشاء مصدر لقوائم الأنماط التي تم إنشاؤها والتي يمكن تعديلها باستخدام الآلية الحالية الموضّحة أعلاه.
الخطوة الأولى هي إنشاء النص المصدر. يخزّن محرّك الأنماط في المتصفّح قواعد CSS في الفئة CSSStyleSheet
. وهذه الفئة هي الفئة التي يمكنك إنشاء نُسخ منها من JavaScript كما ناقشنا سابقًا. في ما يلي الرمز البرمجي لإنشاء النص المصدر:
String InspectorStyleSheet::CollectStyleSheetRules() {
StringBuilder builder;
for (unsigned i = 0; i < page_style_sheet_->length(); i++) {
builder.Append(page_style_sheet_->item(i)->cssText());
builder.Append('\n');
}
return builder.ToString();
}
ويكرّر الإجراء القواعد المتوفّرة في مثيل CSSStyleSheet وينشئ سلسلة واحدة منها. يتمّ استدعاء هذه الطريقة عند إنشاء مثيل لفئة InspectorStyleSheet. تُغلِّف فئة InspectorStyleSheet مثيل CSSStyleSheet وتستخرج بيانات وصفية إضافية مطلوبة من خلال "أدوات المطوّرين":
void InspectorStyleSheet::UpdateText() {
String text;
bool success = InspectorStyleSheetText(&text);
if (!success)
success = InlineStyleSheetText(&text);
if (!success)
success = ResourceStyleSheetText(&text);
if (!success)
success = CSSOMStyleSheetText(&text);
if (success)
InnerSetText(text, false);
}
في هذا المقتطف، نرى CSSOMStyleSheetText
التي تستدعي CollectStyleSheetRules
داخليًا. يتمّ استدعاء CSSOMStyleSheetText
إذا لم يكن ملفّ التنسيق مضمّنًا أو ملفّ تنسيق مورد. في الأساس، يتيح هذان المقتطفان حاليًا إجراء تعديلات أساسية على أوراق الأنماط التي يتم إنشاؤها باستخدام أداة الإنشاء new CSSStyleSheet()
.
ومن الحالات الخاصة أوراق الأنماط المرتبطة بعلامة <style>
التي تم تغييرها باستخدام واجهة برمجة التطبيقات CSSOM API. في هذه الحالة، يحتوي ملف تنسيق الصفحات على نص المصدر وقواعد إضافية غير متوفّرة في المصدر. لحلّ هذه المشكلة، نقدّم طريقة لدمج هذه القواعد الإضافية في النص المصدر. ويُعدّ الترتيب مهمًا هنا لأنّه يمكن إدراج قواعد CSS في منتصف النص المصدر الأصلي. على سبيل المثال، تخيل أنّ عنصر <style>
الأصلي كان يتضمّن النص التالي:
/* comment */
.rule1 {}
.rule3 {}
بعد ذلك، أدرجت الصفحة بعض القواعد الجديدة باستخدام JS API، ما أدّى إلى ترتيب القواعد التالي: .rule0 و.rule1 و.rule2 و.rule3 و.rule4. يجب أن يكون النص المصدر الناتج بعد عملية الدمج على النحو التالي:
.rule0 {}
/* comment */
.rule1 {}
.rule2 {}
.rule3 {}
.rule4 {}
إنّ الحفاظ على التعليقات الأصلية والبادئة مهمة لعملية التعديل لأنّ مواضع النص المصدر للقواعد يجب أن تكون دقيقة.
هناك جانب آخر خاص بأوراق الأنماط CSS-in-JS وهو أنّ يمكن للصفحة تغييرها في أي وقت. إذا لم تكن قواعد CSSOM الفعلية متزامنة مع النسخة النصية، لن يعمل التعديل. لهذا الغرض، قدّمنا ما يُعرف باسم الاستكشاف، الذي يسمح للمتصفح بإعلام الجزء الخلفي من DevTools عند حدوث تغيير في ملف أسلوب التنسيق. بعد ذلك، تتم مزامنة أوراق الأنماط التي تم تغييرها أثناء الطلب التالي إلى CSS.getMatchedStylesForNode.
بعد توفير كل هذه العناصر، أصبح بإمكانك استخدام ميزة CSS-in-JS، ولكن أردنا تحسين واجهة المستخدم للإشارة إلى ما إذا تم إنشاء جدول أسلوب. أضفنا سمة جديدة باسم isConstructed
إلى CSS.CSSStyleSheetHeader في CDP والتي تستخدمها الواجهة الأمامية لعرض مصدر قاعدة CSS بشكل صحيح:
الاستنتاجات
لتلخيص قصتنا هنا، لقد اطّلعنا على حالات الاستخدام ذات الصلة بـ CSS-in-JS التي لا تتوافق مع "أدوات المطوّر"، وشرحنا الحلّ المتوافق مع حالات الاستخدام هذه. إنّ الجزء المثير للاهتمام في هذا التنفيذ هو أنّنا تمكّنا من الاستفادة من الوظائف الحالية من خلال جعل قواعد CSSOM CSS تحتوي على نص مصدر عادي، ما يتجنّب الحاجة إلى إعادة تصميم ميزة تعديل الأنماط بالكامل في "أدوات المطوّر".
لمزيد من المعلومات الأساسية، يمكنك الاطّلاع على اقتراح التصميم أو خطأ التتبّع في Chromium الذي يشير إلى جميع الإصلاحات ذات الصلة.
تنزيل قنوات المعاينة
ننصحك باستخدام إصدار Canary أو Dev أو الإصدار التجريبي من Chrome كمتصفّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات DevTools، وتتيح لك اختبار واجهات برمجة تطبيقات منصات الويب المتطوّرة، وتساعدك في العثور على المشاكل في موقعك الإلكتروني قبل أن يعثر عليها المستخدمون.
التواصل مع فريق "أدوات مطوّري البرامج في Chrome"
استخدِم الخيارات التالية لمناقشة الميزات الجديدة أو التحديثات أو أي شيء آخر مرتبط بـ "أدوات مطوّري البرامج".
- يمكنك إرسال الملاحظات وطلبات الميزات إلينا على crbug.com.
- يمكنك الإبلاغ عن مشكلة في "أدوات مطوّري البرامج" باستخدام رمز خيارات إضافية > مساعدة > الإبلاغ عن مشكلة في "أدوات مطوّري البرامج" في "أدوات مطوّري البرامج".
- يمكنك نشر تغريدة على Twitter على @ChromeDevTools.
- يمكنك إضافة تعليقات على فيديوهات YouTube التي تعرض الميزات الجديدة في "أدوات مطوّري البرامج" أو فيديوهات YouTube التي تعرض نصائح حول "أدوات مطوّري البرامج".