आउट-ऑफ़-ऑर्डर (ओओओ) एचटीएमएल स्ट्रीमिंग

आउट-ऑफ़-ऑर्डर (ओओओ) एचटीएमएल स्ट्रीमिंग, एचटीएमएल की पारंपरिक "टॉप-टू-बॉटम" लीनियर प्रोसेसिंग का एक विकल्प है. इसे डिक्लेरेटिव पार्शियल अपडेट भी कहा जाता है. इसकी मदद से, डेवलपर किसी दस्तावेज़ में पहले से प्लेसहोल्डर तय कर सकते हैं. साथ ही, उन्हें उसी नेटवर्क स्ट्रीम में बाद में आने वाले कॉन्टेंट या नए इंपरेटिव JavaScript स्ट्रीमिंग एपीआई के ज़रिए "पैच" कर सकते हैं.

खास जानकारी

इस सुविधा में दो मुख्य तरीके शामिल हैं:

  1. डिक्लेरेटिव पैचिंग (एचटीएमएल पर आधारित): यह प्रोसेसिंग के नए निर्देशों (<?marker>, <?start>, <?end>) और <template for> का इस्तेमाल करके, डीओएम में कॉन्टेंट को स्वैप करता है. ऐसा तब होता है, जब कॉन्टेंट सर्वर से स्ट्रीम हो रहा होता है.
  2. इंपेरेटिव सेटिंग और स्ट्रीमिंग (JS-आधारित): नए तरीकों का एक सुइट (जैसे, streamHTML(), setHTMLUnsafe()) जो एचटीएमएल सेट करने या सीधे DOM एलिमेंट में रीडेबल स्ट्रीम को पाइप करने की अनुमति देता है. इसमें नेटिव परफ़ॉर्मेंस और वैकल्पिक स्क्रिप्ट को लागू करने की सुविधा मिलती है.

सबसे सही तरीके

  • पेज के ऊपरी हिस्से में दिखने वाले कॉन्टेंट को प्राथमिकता दें: ज़रूरी यूज़र इंटरफ़ेस (यूआई) एलिमेंट (हेडर, हीरो, मुख्य नेविगेशन, मुख्य कॉन्टेंट) को पहले लोड करें. टिप्पणियों, विज्ञापनों या मिलते-जुलते कॉन्टेंट जैसे "ज़्यादा डेटा खर्च करने वाले" या कम प्राथमिकता वाले कॉम्पोनेंट के लिए, प्लेसहोल्डर का इस्तेमाल करें.
  • नेटिव लोडिंग स्टेट लागू करना: फ़ॉलबैक कॉन्टेंट को रैप करने के लिए, <?start> और <?end> मार्कर का इस्तेमाल करें. जब <template for> आता है, तब ब्राउज़र इन मार्कर के बीच की हर चीज़ को अपने-आप बदल देता है.
  • लेआउट शिफ़्ट होने में लगने वाले समय (सीएलएस) को कम करना: प्लेसहोल्डर के लिए हमेशा सही डाइमेंशन दें. अगर कॉन्टेंट के फ़ाइनल साइज़ की जानकारी नहीं है, तो स्केलेटन स्क्रीन या सीएसएस aspect-ratio का इस्तेमाल करें. इससे स्पेस रिज़र्व किया जा सकता है और कॉन्टेंट को अचानक शिफ़्ट होने से रोका जा सकता है.
  • सुलभता और फ़ोकस मैनेजमेंट: ध्यान रखें कि बिना क्रम के किए गए अपडेट, स्क्रीन रीडर इस्तेमाल करने वाले लोगों को भ्रमित कर सकते हैं. ज़रूरी अपडेट के लिए, aria-live रीजन का इस्तेमाल करें. साथ ही, यह पक्का करें कि अगर ऐक्टिव एलिमेंट वाले प्लेसहोल्डर को बदला जाता है, तो फ़ोकस न हटे.

लागू करने से जुड़ी जानकारी

1. डिक्लेरेटिव एचटीएमएल मार्कर

ब्राउज़र, प्रोसेस करने से जुड़े खास निर्देशों को ढूंढता है, ताकि यह पता लगाया जा सके कि कॉन्टेंट को कहां पैच करना है.

<!-- A simple insertion point -->
<div id="sidebar">
  <?marker name="dynamic-comments">
</div>

<!-- A replacement range with loading state -->
<main>
  <?start name="main-content">
    <div class="skeleton">Loading content...</div>
  <?end>
</main>

... (other content) ...

<!-- Later in the same stream, provide the content -->
<template for="dynamic-comments">
  <div class="comments">...</div>
</template>

<template for="main-content">
  <article>
    <h1>The Real Content</h1>
    <p>This replaces the skeleton div automatically.</p>
  </article>
</template>

जब कोई <template> किसी इंसर्शन पॉइंट की जगह ले लेता है, तो वह इंसर्शन पॉइंट अब मौजूद नहीं रहता और उसे फिर से इस्तेमाल नहीं किया जा सकता. हालांकि, <template> में इंसर्शन पॉइंट हो सकते हैं. इनका इस्तेमाल, स्ट्रीम में बाद में किया जा सकता है.

 <?start name="replaced-content">
  <div class="skeleton">
<?end>
<!-- Later in the same stream, provide initial content -->
<template for="replaced-content">
  <?start name="replaced-content">
    <div>Quickly computed result</div>
  <?end>
</template>
<!-- Later in the same stream, provide full content -->
<template for="replaced-content">
  <?start name="replaced-content">
    <div>Full result</div>
  <?end>
</template>

2. इंपरेटिव जेएस स्ट्रीमिंग

ब्राउज़र, डीओएम को स्टैटिक तरीके से (स्ट्रिंग से) या स्ट्रीम के ज़रिए अपडेट करने के लिए, 24 तरीकों (छह कार्रवाइयां, हर एक के चार वैरिएशन) का सुइट उपलब्ध कराता है.

एपीआई रेफ़रंस मैट्रिक्स

कार्रवाई स्टैटिक (सुरक्षित) स्ट्रीमिंग (सुरक्षित) स्टैटिक (असुरक्षित) स्ट्रीमिंग (असुरक्षित)
सेट करें setHTML() streamHTML() setHTMLUnsafe() streamHTMLUnsafe()
बदलें replaceWithHTML() streamReplaceWithHTML() replaceWithHTMLUnsafe() streamReplaceWithHTMLUnsafe()
पहले beforeHTML() streamBeforeHTML() beforeHTMLUnsafe() streamBeforeHTMLUnsafe()
Prepend prependHTML() streamPrependHTML() prependHTMLUnsafe() streamPrependHTMLUnsafe()
जोड़ें appendHTML() streamAppendHTML() appendHTMLUnsafe() streamAppendHTMLUnsafe()
बाद में afterHTML() streamAfterHTML() afterHTMLUnsafe() streamAfterHTMLUnsafe()

खास कॉन्सेप्ट

  • सुरक्षित बनाम असुरक्षित:
    • setHTML() जैसे सुरक्षित तरीकों में, डिफ़ॉल्ट रूप से पहले से मौजूद सैनिटाइज़र का इस्तेमाल किया जाता है. इससे <script> टैग जैसे संभावित तौर पर खतरनाक कॉन्टेंट को हटाया जाता है. डिफ़ॉल्ट सैनिटाइज़र के अलावा, विकल्पों में कस्टम Sanitizer ऑब्जेक्ट को पास किया जा सकता है.
    • असुरक्षित तरीके (जैसे, setHTMLUnsafe()) डिफ़ॉल्ट रूप से सैनिटाइज़ नहीं करते. हालांकि, आपके पास अब भी कस्टम Sanitizer पास करने का विकल्प है. नए कॉन्टेंट में स्क्रिप्ट को चलाने की अनुमति देने के लिए, आपको विकल्पों में साफ़ तौर पर { runScripts: true } पास करना होगा. अहम जानकारी: असुरक्षित तरीकों का इस्तेमाल सिर्फ़ भरोसेमंद कॉन्टेंट के साथ करें. ऐसा तब करें, जब सुरक्षित तरीके काम न करें.
  • स्टैटिक बनाम स्ट्रीमिंग:
    • Static तरीके, स्ट्रिंग (या TrustedHTML) लेते हैं और उसे तुरंत लागू करते हैं.
    • स्ट्रीमिंग के तरीके, WritableStream दिखाते हैं. इससे कॉन्टेंट (जैसे, fetch रिस्पॉन्स से) को सीधे डीओएम में पाइप किया जा सकता है. साथ ही, ब्राउज़र इसे चंक के आने पर रेंडर करेगा.

उदाहरण: फ़ेच रिस्पॉन्स को स्ट्रीम करना

फ़ेच किए गए रिस्पॉन्स को सीधे डीओएम में पाइप किया जा सकता है. इसके लिए, मैन्युअल तरीके से चंक हैंडलिंग की ज़रूरत नहीं होती.

const main = document.querySelector('main');
const response = await fetch('/api/partial-update');

// Pipe the stream directly into the element
await response.body
  .pipeThrough(new TextDecoderStream())
  .pipeTo(main.streamHTMLUnsafe({ runScripts: true }));

// Or use the `textStream()` convenience method which streams directly without needing the intermediate `TextDecoderStream()` step
await response
  .textStream()
  .pipeTo(main.streamHTMLUnsafe({ runScripts: true }))

इस्तेमाल के उदाहरणों का रेफ़रंस मैट्रिक्स

  • आइलैंड आर्किटेक्चर: स्टैटिक एचटीएमएल के ऊपर, इंटरैक्टिव कॉम्पोनेंट को हाइड्रेट करें. इसके लिए, पूरे फ़्रेमवर्क रनटाइम की ज़रूरत नहीं होती.
  • डिफ़र्ड "एक्सपेंसिव" ब्लॉक: पेज के शेल को तुरंत डिलीवर करें और डेटाबेस-हैवी कॉम्पोनेंट उपलब्ध होने पर उन्हें स्ट्रीम करें.
  • एक पेज के ऐप्लिकेशन (एसपीए) से जुड़े अपडेट: एसपीए में बड़े यूज़र इंटरफ़ेस (यूआई) ट्रांज़िशन को स्ट्रीम करने के लिए, streamHTML() का इस्तेमाल करें. इससे आपको पूरे JSON पेलोड और मैन्युअल डीओएम कंस्ट्रक्शन का इंतज़ार नहीं करना पड़ेगा.

एंटी-पैटर्न और चेतावनियां (ऐसा न करें)

  • हर तरह के कॉन्टेंट के लिए, ओओओ स्ट्रीमिंग का इस्तेमाल न करें. किसी पेज को ज़रूरत से ज़्यादा फ़्रैगमेंट करने से, स्ट्रीम की जटिलता बढ़ सकती है. साथ ही, अगर ब्राउज़र छोटे नोड को पैच करने में ज़्यादा समय लेता है, तो कॉन्टेंट लोड होने में देरी हो सकती है.
  • भरोसेमंद टाइप को अनदेखा न करें. भरोसेमंद टाइप लागू होने पर, *Unsafe तरीकों का इस्तेमाल करते समय, पक्का करें कि ज़रूरत पड़ने पर, सैनिटाइज़ किया गया नीति ऑब्जेक्ट पास किया जा रहा हो.
  • स्क्रिप्ट के लागू होने के क्रम का अनुमान न लगाएं. <template for> में मौजूद स्क्रिप्ट, दस्तावेज़ में पैच होते ही लागू हो जाएंगी. इस बात पर भरोसा न करें कि वे अन्य डेफ़र्ड टेंप्लेट के हिसाब से किसी खास क्रम में लागू होंगे.
  • पॉलीफ़िल रणनीति के बिना इसका इस्तेमाल न करें. पक्का करें कि आपके पास फ़ॉलबैक हो या polyfills (html-setters-polyfill और template-for-polyfill) का इस्तेमाल करें, ताकि आपके ज़रूरी ब्राउज़र तब तक काम करते रहें, जब तक यह सुविधा Baseline नहीं बन जाती.

फ़ॉलबैक रणनीतियां

template-for-polyfill और html-setters-polyfill जैसे पॉलीफ़िल का इस्तेमाल करके, एपीआई के काम करने के तरीके को उन ब्राउज़र पर भी लागू किया जा सकता है जो इसे सपोर्ट नहीं करते.

जिन ब्राउज़र में html-processing-instructions काम नहीं करता वे <?marker>, <?start>, और <?end> को टिप्पणियों के तौर पर पार्स करते हैं. template-for-polyfill अब भी इन टिप्पणियों को मार्कर के तौर पर पहचानता है. इसलिए, सभी ब्राउज़र के लिए एक ही प्रोसेसिंग निर्देश सिंटैक्स का इस्तेमाल करें. मार्कर को एचटीएमएल टिप्पणियों या एलिमेंट के तौर पर फिर से न लिखें. ऐसा करने पर, ये मार्कर उन ब्राउज़र पर काम नहीं करेंगे जो इन्हें सपोर्ट नहीं करते.