पहले से रेंडर करने का मतलब है कि सर्वर से कस्टम एलिमेंट का मार्कअप भेजना. इसमें उसका शैडो ट्री भी शामिल है. इससे कॉम्पोनेंट को स्टाइल और स्ट्रक्चर किया जाता है. ऐसा किसी भी JavaScript के चलने से पहले किया जाता है. इसके लिए, मुख्य प्लैटफ़ॉर्म प्रिमिटिव डिक्लेरेटिव शैडो डीओएम (डीएसडी) है: पार्सर, शैडो रूट को सिर्फ़ एचटीएमएल से अटैच करता है. इसके बाद, एलिमेंट को उसकी क्लास के हिसाब से अपग्रेड ("हाइड्रेट") किया जाता है. हालांकि, ऐसा तब होता है, जब कोई क्लास रजिस्टर हो. इस पैटर्न का इस्तेमाल सर्वर-साइड रेंडरिंग, स्ट्रीमिंग, और बिना स्टाइल वाले कॉन्टेंट (एफ़ओयूसी) की फ़्लैश से बचने के लिए करें.
डिक्लेरेटिव शैडो रूट बनाना
होस्ट के पहले चाइल्ड के तौर पर, shadowrootmode एट्रिब्यूट के साथ <template> को नेस्ट करें. पार्सर, अपने कॉन्टेंट को शैडो रूट के तौर पर अटैच करता है और टेंप्लेट को हटा देता है. इसके लिए, किसी स्क्रिप्ट की ज़रूरत नहीं होती.
<my-card>
<template shadowrootmode="open">
<style>
.card { border: 1px solid; border-radius: 8px; padding: 1rem; }
</style>
<div class="card">
<slot name="header"></slot>
<div class="body"><slot></slot></div>
</div>
</template>
<!-- Light DOM children are projected into the slots above. -->
<h2 slot="header">Server-rendered title</h2>
<p>Visible and styled before JS loads.</p>
</my-card>
हाइड्रेशन का समय
मैच होने वाली क्लास रजिस्टर होने पर, ब्राउज़र होस्ट को अपग्रेड कर देता है. शैडो रूट पहले से मौजूद होने की वजह से, कंस्ट्रक्टर को बिना सोचे-समझे दूसरा शैडो रूट नहीं बनाना चाहिए:
class MyCard extends HTMLElement {
constructor() {
super();
// Reuse the server-rendered shadow root if present; only create one if absent.
if (!this.shadowRoot) {
this.attachShadow({ mode: 'open' });
this.shadowRoot.append(template.content.cloneNode(true));
}
// Hydrate in place: attach listeners once against existing markup (not unguarded
// in connectedCallback, which re-runs if the element moves in the DOM), and do
// NOT re-render; that would discard the server's DOM and flash.
this.shadowRoot.getElementById('toggle')
?.addEventListener('click', () => this.toggleAttribute('open'));
}
}
ज़्यादातर मामलों में, shadowrootmode="open" (closed नहीं) सेट करें, ताकि स्क्रिप्ट और टूल, this.shadowRoot तक पहुंच सकें. सर्वर पर या टेस्ट में, किसी मौजूदा शैडो रूट को एचटीएमएल में वापस सीरियलाइज़ करने के लिए, getHTML({ serializableShadowRoots: true }) का इस्तेमाल करें और रूट को serializable: true के साथ अटैच करें.
एफ़ओयूसी से बचना
डीएसडी, फ़र्स्ट पेंट पर सिर्फ़ तब सही तरीके से रेंडर होता है, जब स्टाइल को डिक्लेरेटिव टेंप्लेट में शामिल किया गया हो. इसे बनाए रखने के लिए:
- कॉम्पोनेंट सीएसएस को
<template shadowrootmode>(<style>टैग या<link>) के अंदर रखें, न कि स्क्रिप्ट से लोड की गई किसी अलग शीट में. my-card:not(:defined) { … }को सिर्फ़ उन स्टाइल के साथ जोड़ें जिनके लिए JS का इंतज़ार करना ज़रूरी है. आम तौर पर, पेज-लेवल के गार्ड नियम, जैसे कि क्लाइंट-रेंडर किए गए इंस्टेंस पर फ़ेड-आउट होना, जो एसएसआर पास को मिस करते हैं. ये लाइट-डीओएम (पेज) स्टाइलशीट में मौजूद होते हैं, क्योंकि शैडो रूट अब तक वहां मौजूद नहीं है और:hostसिलेक्टर बाहर से लागू नहीं होते. डीएसडी टेंप्लेट में मौजूद स्ट्रक्चरल स्टाइल के लिए, इस तरह के गार्ड की ज़रूरत नहीं होती.- हाइड्रेशन के दौरान, शैडो ट्री को फिर से रेंडर न करें. सर्वर मार्कअप को आधिकारिक मानें और उसमें बिहेवियर अटैच करें.
फ़ॉलबैक रणनीतियां
shadowrootmode को पार्स न करने वाले इंजन में, टेंप्लेट इनर्ट होता है और उसका कॉन्टेंट शैडो रूट के तौर पर अटैच नहीं होता. इस (Object.hasOwn(HTMLTemplateElement.prototype, 'shadowRootMode')) का पता लगाएं. अगर यह मौजूद नहीं है, तो अपग्रेड के दौरान उसी मार्कअप से शैडो रूट को अटैच करें, ताकि कॉम्पोनेंट अब भी रेंडर हो सके.