DevTools में CSS-in-JS की सहायता

Alex Rudenko
Alex Rudenko

इस लेख में, DevTools में CSS-in-JS के साथ काम करने की सुविधा के बारे में बताया गया है. यह सुविधा, Chrome 85 के बाद से उपलब्ध है. आम तौर पर, CSS-in-JS का मतलब क्या है और यह सामान्य सीएसएस से कैसे अलग है, इस बारे में भी बताया गया है. सामान्य सीएसएस, DevTools में लंबे समय से काम करती आ रही है.

CSS-in-JS क्या है?

CSS-in-JS की परिभाषा काफ़ी अस्पष्ट है. आम तौर पर, यह JavaScript का इस्तेमाल करके सीएसएस कोड को मैनेज करने का तरीका है. उदाहरण के लिए, इसका मतलब यह हो सकता है कि सीएसएस कॉन्टेंट को JavaScript का इस्तेमाल करके तय किया गया है और ऐप्लिकेशन, फ़्लाइट पर सीएसएस का फ़ाइनल आउटपुट जनरेट करता है.

DevTools के संदर्भ में, CSS-in-JS का मतलब है कि CSSOM API का इस्तेमाल करके, सीएसएस कॉन्टेंट को पेज में इंजेक्ट किया जाता है. सामान्य सीएसएस को <style> या <link> एलिमेंट का इस्तेमाल करके इंजेक्ट किया जाता है. साथ ही, इसका एक स्टैटिक सोर्स होता है, जैसे कि डीओएम नोड या नेटवर्क रिसॉर्स. इसके उलट, CSS-in-JS में अक्सर स्टैटिक सोर्स नहीं होता. यहां एक खास मामला यह है कि <style> एलिमेंट का कॉन्टेंट, CSSOM API का इस्तेमाल करके अपडेट किया जा सकता है. इस वजह से, सोर्स, असल सीएसएस स्टाइलशीट के साथ सिंक नहीं हो पाता.

अगर styled-component, Emotion, JSS जैसी किसी भी CSS-in-JS लाइब्रेरी का इस्तेमाल किया जाता है, तो डेवलपमेंट मोड और ब्राउज़र के हिसाब से, लाइब्रेरी 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];

DevTools में सीएसएस की सहायता

DevTools में, सीएसएस के साथ काम करते समय सबसे ज़्यादा इस्तेमाल की जाने वाली सुविधा स्टाइल पैनल है. स्टाइल पैनल में, यह देखा जा सकता है कि किसी खास एलिमेंट पर कौनसे नियम लागू होते हैं. साथ ही, नियमों में बदलाव करके, पेज पर रीयल टाइम में बदलाव देखे जा सकते हैं.

पिछले साल से पहले, CSSOM API का इस्तेमाल करके बदले गए सीएसएस नियमों के लिए सहायता काफ़ी सीमित थी: सिर्फ़ लागू किए गए नियम देखे जा सकते थे, लेकिन उनमें बदलाव नहीं किया जा सकता था. पिछले साल हमारा मुख्य लक्ष्य, स्टाइल पैनल का इस्तेमाल करके CSS-in-JS नियमों में बदलाव करने की सुविधा देना था. कभी-कभी हम CSS-in-JS स्टाइल को "बनाया गया" भी कहते हैं. इससे पता चलता है कि वे वेब एपीआई का इस्तेमाल करके बनाए गए थे.

आइए, DevTools में स्टाइल में बदलाव करने की सुविधा के बारे में ज़्यादा जानें.

DevTools में स्टाइल में बदलाव करने की सुविधा

DevTools में स्टाइल में बदलाव करने की सुविधा

DevTools में कोई एलिमेंट चुनने पर, स्टाइल पैनल दिखता है. स्टाइल पैनल, एलिमेंट पर लागू होने वाले सीएसएस नियमों को पाने के लिए, CSS.getMatchedStylesForNode नाम का सीडीपी कमांड जारी करता है. सीडीपी का मतलब है, Chrome DevTools प्रोटोकॉल. यह एक एपीआई है, जिसकी मदद से DevTools के फ़्रंटएंड को, जांचे गए पेज के बारे में ज़्यादा जानकारी मिलती है.

इस्तेमाल किए जाने पर, CSS.getMatchedStylesForNode दस्तावेज़ में मौजूद सभी स्टाइलशीट की पहचान करता है और ब्राउज़र के सीएसएस पार्सर का इस्तेमाल करके उन्हें पार्स करता है. इसके बाद, यह एक इंडेक्स बनाता है, जो हर सीएसएस नियम को स्टाइलशीट सोर्स में किसी पोज़िशन से जोड़ता है.

आपके मन में यह सवाल आ सकता है कि सीएसएस को फिर से पार्स करने की ज़रूरत क्यों है? यहां समस्या यह है कि परफ़ॉर्मेंस की वजह से, ब्राउज़र को सीएसएस नियमों की सोर्स पोज़िशन से कोई फ़र्क़ नहीं पड़ता. इसलिए, वह उन्हें सेव नहीं करता. हालांकि, सीएसएस में बदलाव करने के लिए, DevTools को सोर्स पोज़िशन की ज़रूरत होती है. हम नहीं चाहते कि Chrome के सामान्य उपयोगकर्ताओं को परफ़ॉर्मेंस में कमी का असर पड़े. हालांकि, हम चाहते हैं कि DevTools के उपयोगकर्ताओं के पास सोर्स पोज़िशन का ऐक्सेस हो. फिर से पार्स करने के इस तरीके से, इस्तेमाल के दोनों उदाहरणों में कम से कम नुकसान होता है.

इसके बाद, CSS.getMatchedStylesForNode लागू करने की प्रोसेस, ब्राउज़र के स्टाइल इंजन से, दिए गए एलिमेंट से मैच करने वाले सीएसएस नियम देने के लिए कहती है. आखिर में, यह तरीका स्टाइल इंजन से मिले नियमों को सोर्स कोड से जोड़ता है. साथ ही, सीएसएस नियमों के बारे में स्ट्रक्चर्ड जवाब देता है, ताकि DevTools को पता चल सके कि नियम का कौनसा हिस्सा सिलेक्टर या प्रॉपर्टी है. इससे DevTools, सिलेक्टर और प्रॉपर्टी में अलग-अलग बदलाव कर सकता है.

अब बदलाव करने के बारे में जानें. याद रखें कि CSS.getMatchedStylesForNode हर नियम के लिए सोर्स पोज़िशन दिखाता है? एडिटिंग के लिए यह ज़रूरी है. किसी नियम में बदलाव करने पर, DevTools एक और सीडीपी कमांड जारी करता है, जो असल में पेज को अपडेट करता है. इस निर्देश में, अपडेट किए जा रहे नियम के फ़्रैगमेंट की मूल स्थिति और नया टेक्स्ट शामिल होता है. फ़्रैगमेंट को इस टेक्स्ट से अपडेट करना होता है.

बैकएंड पर, बदलाव करने के कॉल को मैनेज करते समय, DevTools टारगेट स्टाइलशीट को अपडेट करता है. यह स्टाइलशीट सोर्स की कॉपी को भी अपडेट करता है. साथ ही, अपडेट किए गए नियम के लिए सोर्स की पोज़िशन को भी अपडेट करता है. बदलाव करने के अनुरोध के जवाब में, DevTools के फ़्रंटएंड को उस टेक्स्ट फ़्रैगमेंट की अपडेट की गई पोज़िशन मिलती है जिसे अभी-अभी अपडेट किया गया है.

इससे पता चलता है कि DevTools में CSS-in-JS में बदलाव करने की सुविधा, पहले से काम क्यों नहीं करती: CSS-in-JS का कोई असल सोर्स कहीं सेव नहीं होता और CSS नियम, CSSOM डेटा स्ट्रक्चर में ब्राउज़र की मेमोरी में मौजूद होते हैं.

हमने CSS-in-JS के लिए सहायता कैसे जोड़ी

इसलिए, CSS-in-JS नियमों में बदलाव करने के लिए, हमने यह तय किया कि सबसे अच्छा तरीका यह होगा कि हम कॉन्स्ट्रक्ट की गई स्टाइलशीट का सोर्स बनाएं. इसमें ऊपर बताए गए मौजूदा तरीके का इस्तेमाल करके बदलाव किया जा सकता है.

सबसे पहले, सोर्स टेक्स्ट बनाएं. ब्राउज़र का स्टाइल इंजन, सीएसएस नियमों को 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 इंस्टेंस को रैप करती है और DevTools के लिए ज़रूरी अतिरिक्त मेटाडेटा को निकालती है:

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 का इस्तेमाल करके बदलाव किया गया है. इस मामले में, स्टाइलशीट में सोर्स टेक्स्ट और ऐसे अतिरिक्त नियम शामिल होते हैं जो सोर्स में मौजूद नहीं होते. इस मामले को हल करने के लिए, हमने उन अतिरिक्त नियमों को सोर्स टेक्स्ट में मर्ज करने का एक तरीका पेश किया है. यहां क्रम का ध्यान रखना ज़रूरी है, क्योंकि सीएसएस नियमों को ओरिजनल सोर्स टेक्स्ट के बीच में डाला जा सकता है. उदाहरण के लिए, मान लें कि ओरिजनल <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 में बदलाव करने की सुविधा पहले से ही काम कर रही है. हालांकि, हम यूज़र इंटरफ़ेस (यूआई) को बेहतर बनाना चाहते थे, ताकि यह पता चल सके कि स्टाइलशीट बनाई गई है या नहीं. हमने CDP के CSS.CSSStyleSheetHeader में isConstructed नाम का एक नया एट्रिब्यूट जोड़ा है. फ़्रंटएंड, सीएसएस नियम के सोर्स को सही तरीके से दिखाने के लिए इसका इस्तेमाल करता है:

ऐसी स्टाइलशीट जिसे बनाया जा सकता है

मीटिंग में सामने आए नतीजे

यहां अपनी कहानी को फिर से बताने के लिए, हमने CSS-in-JS से जुड़े उन काम के इस्तेमाल के उदाहरणों को देखा जिनके साथ DevTools काम नहीं करता. साथ ही, उन इस्तेमाल के उदाहरणों के साथ काम करने के लिए समाधान के बारे में बताया. इस सुविधा को लागू करने का दिलचस्प हिस्सा यह है कि हमने CSSOM CSS नियमों में रेगुलर सोर्स टेक्स्ट जोड़कर, मौजूदा सुविधा का फ़ायदा उठाया. इससे, DevTools में स्टाइल में बदलाव करने की सुविधा को फिर से डिज़ाइन करने की ज़रूरत नहीं पड़ी.

ज़्यादा जानकारी के लिए, हमारा डिज़ाइन प्रस्ताव या Chromium का ट्रैकिंग बग देखें. इसमें, इससे जुड़े सभी पैच का रेफ़रंस दिया गया है.

झलक वाले चैनल डाउनलोड करना

Chrome कैनरी, डेवलपर या बीटा को अपने डिफ़ॉल्ट डेवलपमेंट ब्राउज़र के तौर पर इस्तेमाल करें. इन झलक वाले चैनलों की मदद से, आपको DevTools की नई सुविधाओं का ऐक्सेस मिलता है. साथ ही, इनसे आपको वेब प्लैटफ़ॉर्म के सबसे नए एपीआई की जांच करने में मदद मिलती है. इसके अलावा, इनकी मदद से उपयोगकर्ताओं से पहले ही अपनी साइट पर समस्याओं का पता लगाया जा सकता है!

Chrome DevTools की टीम से संपर्क करना

DevTools से जुड़ी नई सुविधाओं, अपडेट या किसी भी अन्य चीज़ के बारे में चर्चा करने के लिए, यहां दिए गए विकल्पों का इस्तेमाल करें.