إتاحة CSS-in-JS في "أدوات مطوري البرامج"

Alex Rudenko
Alex Rudenko

تتناول هذه المقالة إتاحة استخدام CSS-in-JS في "أدوات مطوري البرامج" بدءًا من الإصدار Chrome 85، وما نعنيه بشكل عام بلغة 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، ما يؤدي إلى عدم تزامن المصدر مع ورقة أنماط 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 على أنّها "مُنشأة" للإشارة إلى أنّها تم إنشاؤها باستخدام واجهات برمجة تطبيقات الويب.

سنعرض الآن تفاصيل حول عمليات تعديل الأنماط في "أدوات مطوري البرامج".

آلية تعديل الأنماط في "أدوات مطوّري البرامج"

آلية تعديل الأنماط في &quot;أدوات مطوّري البرامج&quot;

عند اختيار عنصر في "أدوات مطوّري البرامج"، يتم عرض لوحة الأنماط. تُصدِر لوحة الأنماط أمرًا في إطار عمل CDP يُسمى CSS.getMatchedStylesForNode للحصول على قواعد CSS التي تنطبق على العنصر. يشير الاختصار CDP إلى بروتوكول أدوات مطوري البرامج في Chrome، وهو عبارة عن واجهة برمجة تطبيقات تتيح للواجهة الأمامية لأدوات مطوّري البرامج الحصول على معلومات إضافية حول الصفحة التي تم فحصها.

عند الاستدعاء، يحدِّد CSS.getMatchedStylesForNode جميع أوراق الأنماط في المستند ويحلّلها باستخدام محلِّل CSS في المتصفّح. بعد ذلك، يتم إنشاء فهرس يربط كل قاعدة CSS بموضع في مصدر جدول الأنماط.

قد تتساءل، لماذا يجب تحليل ملف CSS مرة أخرى؟ تكمن المشكلة هنا في أنّ المتصفح نفسه لا يهتم بمواقع مصادر قواعد CSS لأسباب تتعلّق بالأداء، وبالتالي لا يخزنها. ولكن تحتاج أدوات المطوّرين إلى مواضع المصادر لتتمكّن من تعديل CSS. لا نريد أن يدفع مستخدمو 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. في هذه الحالة، يحتوي ملف تنسيق الصفحات على نص المصدر وقواعد إضافية غير متوفّرة في المصدر. لحلّ هذه المشكلة، نقدّم طريقة لدمج هذه القواعد الإضافية في النص المصدر. ويُعدّ الترتيب مهمًا هنا لأنّه يمكن إدراج قواعد 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"

استخدِم الخيارات التالية لمناقشة الميزات الجديدة أو التحديثات أو أي شيء آخر مرتبط بـ "أدوات مطوّري البرامج".