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

أليكس رودينكو
أليكس رودينكو

تتناول هذه المقالة إتاحة استخدام 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 API، ما يؤدي إلى عدم مزامنة المصدر مع ورقة أنماط CSS الفعلية.

إذا كنت تستخدم أي مكتبة من مكتبة CSS-in-JS (على سبيل المثال، styled-component وEmotion وJSS)، قد تُدخل المكتبة أنماطًا باستخدام واجهات CSSOM API بشكلٍ غير داخلي بناءً على وضع التطوير والمتصفّح.

لنلقِ نظرة على بعض الأمثلة حول كيفية إدخال ورقة أنماط باستخدام 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 باستخدام جزء "Styles" (الأنماط). أحيانًا نُطلق على أنماط CSS-in-JS أيضًا اسم "Createded" للإشارة إلى أنّه تم إنشاؤها باستخدام Web APIs.

لنطّلِع على تفاصيل أعمال تعديل الأنماط في "أدوات مطوري البرامج".

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

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

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

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

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

بعد ذلك، تطلب عملية تنفيذ CSS.getMatchedStylesForNode من محرّك نمط المتصفّح توفير قواعد CSS التي تطابق العنصر المحدّد. وأخيرًا، تربط الطريقة القواعد التي يعرضها محرّك الأنماط برمز المصدر وتوفّر استجابة منظَّمة حول قواعد CSS حتى تتعرّف أدوات مطوّري البرامج على أي جزء من القاعدة يمثّل أداة الاختيار أو الخصائص. تسمح هذه الميزة لأدوات مطوّري البرامج بتعديل أداة الاختيار والخصائص بشكل مستقل.

لنلقِ نظرة الآن على عملية التعديل. هل تذكر أن CSS.getMatchedStylesForNode تعرض مواضع المصدر لكل قاعدة؟ هذا مهم للتعديل. عند تغيير قاعدة، يصدر DevTools أمر 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 {}

بعد ذلك، أدرجت الصفحة بعض القواعد الجديدة باستخدام واجهة برمجة تطبيقات JavaScript، ما أدّى إلى إنشاء الترتيب التالي للقواعد: .rule0 و .rule1 و .rule2 و .rule3 و .rule4 يجب أن يكون نص المصدر الناتج بعد عملية الدمج على النحو التالي:

.rule0 {}
/* comment */
.rule1 {}
.rule2 {}
.rule3 {}
.rule4 {}

يعد الاحتفاظ بالتعليقات الأصلية والمسافة البادئة مهمين لعملية التعديل لأن مواضع النص المصدر للقواعد يجب أن تكون دقيقة.

هناك جانب آخر يميّز أوراق أنماط CSS-in-JS، وهو أنّه يمكن تغييرها في الصفحة في أي وقت. وإذا كانت قواعد CSSOM الفعلية غير متزامنة مع النسخة النصية، لن يتم التعديل. في هذا الصدد، قدّمنا ما يُعرف باسم probe (الفحص) الذي يتيح للمتصفح إرسال إشعار إلى الجزء الخلفي من "أدوات مطوري البرامج" عندما يتم تغيير ورقة أنماط. ثم تتم مزامنة أوراق الأنماط التي تم تغييرها أثناء الاستدعاء التالي لـ CSS.getMatchStylesForNode.

عند تنفيذ جميع هذه الأجزاء، يمكن إجراء تعديلات على CSS-in-JS، ولكننا أردنا تحسين واجهة المستخدم للإشارة إلى ما إذا كان قد تم إنشاء ورقة أنماط. أضفنا سمة جديدة تُسمى isConstructed إلى CSS.CSSStyleSheetHeader في CDP تستخدمها الواجهة الأمامية لعرض مصدر قاعدة CSS بشكل صحيح:

ورقة أنماط قابلة للإنشاء

الاستنتاجات

لتلخيص قصتنا هنا، تناولنا حالات الاستخدام ذات الصلة المتعلّقة بأداة CSS-in-JS التي لم تتوافق معها أدوات مطوّري البرامج، كما عرضنا الحل لدعم حالات الاستخدام هذه. الجزء المثير للاهتمام من عملية التنفيذ هذه هو أنّنا تمكّنا من الاستفادة من الوظائف الحالية من خلال إضافة نص مصدر عادي إلى قواعد CSSOM، ما تجنّب الحاجة إلى إعادة تصميم تعديلات الأنماط بالكامل في "أدوات مطوري البرامج".

لمزيد من المعلومات الأساسية، يمكنك الاطّلاع على اقتراح التصميم أو خطأ التتبُّع في Chromium الذي يشير إلى جميع رموز التصحيح ذات الصلة.

تنزيل قنوات المعاينة

يمكنك استخدام إصدار Canary أو إصدار مطوّري البرامج أو الإصدار التجريبي من Chrome ليكون متصفِّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات أدوات مطوّري البرامج، واختبار واجهات برمجة التطبيقات المتطورة للأنظمة الأساسية للويب، والعثور على المشاكل في موقعك الإلكتروني قبل أن يتمكّن المستخدمون من ذلك.

التواصل مع فريق "أدوات مطوري البرامج في Chrome"

يمكنك استخدام الخيارات التالية لمناقشة الميزات والتغييرات الجديدة في المشاركة، أو أي موضوع آخر مرتبط بـ "أدوات مطوري البرامج".

  • يمكنك إرسال اقتراحات أو ملاحظات إلينا عبر crbug.com.
  • يمكنك الإبلاغ عن مشكلة في "أدوات مطوري البرامج" باستخدام خيارات إضافية   المزيد > مساعدة > الإبلاغ عن مشاكل في "أدوات مطوري البرامج" في "أدوات مطوري البرامج".
  • نشر تغريدة على @ChromeDevTools
  • يمكنك إضافة تعليقات على الميزات الجديدة في الفيديوهات على YouTube في "أدوات مطوري البرامج" أو الفيديوهات على YouTube التي تتضمّن نصائح حول أدوات مطوّري البرامج.