एचटीएमएल इंपोर्ट

वेब के लिए शामिल करें

इंपोर्ट क्यों करें?

इस बारे में सोचें कि वेब पर, अलग-अलग तरह के संसाधन कैसे लोड किए जाते हैं. JS के लिए हमारे पास <script src> हैं. सीएसएस के लिए, शायद <link rel="stylesheet"> पर जाएं. इमेज के लिए, यह <img> है. वीडियो में <video> है. ऑडियो, <audio>... मुद्दे की बात करें! वेब के ज़्यादातर कॉन्टेंट में, खुद को लोड करने का आसान और निर्देश देने वाला तरीका होता है. एचटीएमएल के लिए ऐसा नहीं है. आपके पास ये विकल्प हैं:

  1. <iframe> - प्रयास किया हुआ और सही लेकिन भारी वज़न. Iframe की सामग्री आपके पेज की तुलना में पूरी तरह से एक अलग संदर्भ में होती है. हालांकि, यह एक अच्छी सुविधा है, लेकिन इससे और मुश्किलें आती हैं. (फ़्रेम के साइज़ को इसके कॉन्टेंट के मुताबिक रैप करना मुश्किल होता है. इसे स्क्रिप्ट में डालना या शुरू करना बहुत ही मुश्किल होता है. इसे स्टाइल करना करीब-करीब नामुमकिन होता है).
  2. AJAX - मुझे xhr.responseType="document" पसंद है, लेकिन आपका मतलब है कि एचटीएमएल लोड करने के लिए मुझे JS चाहिए? यह सही नहीं लग रहा है.
  3. CrazyHacksTM - स्ट्रिंग में जोड़ा गया, टिप्पणियों के तौर पर छिपाया गया (उदाहरण के लिए, <script type="text/html">). वाह!

विडंबना देखें? वेब का सबसे बुनियादी कॉन्टेंट, एचटीएमएल पर काम करने के लिए बहुत मेहनत करनी पड़ती है. अच्छी बात यह है कि वेब कॉम्पोनेंट यहां मौजूद हैं, जो हमें ट्रैक पर वापस लाने में मदद करते हैं.

YouTube TV का इस्तेमाल शुरू करना

एचटीएमएल इंपोर्ट, वेब कॉम्पोनेंट के कास्ट का हिस्सा है. इसकी मदद से, अन्य एचटीएमएल दस्तावेज़ों में एचटीएमएल दस्तावेज़ों को शामिल किया जा सकता है. आप मार्कअप तक सीमित नहीं हैं. इंपोर्ट में सीएसएस, JavaScript या ऐसी कोई भी चीज़ शामिल हो सकती है जो .html फ़ाइल में हो सकती है. दूसरे शब्दों में, इससे मिलते-जुलते एचटीएमएल/CSS/JS लोड करने के लिए एक शानदार टूल इंपोर्ट हो जाता है.

बुनियादी बातें

<link rel="import"> एलान करके अपने पेज पर इंपोर्ट शामिल करें:

<head>
    <link rel="import" href="/path/to/imports/stuff.html">
</head>

इंपोर्ट किए गए किसी यूआरएल को इंपोर्ट करने की जगह कहा जाता है. किसी दूसरे डोमेन से कॉन्टेंट लोड करने के लिए, इंपोर्ट की जाने वाली जगह पर सीओआरएस की सुविधा चालू होनी चाहिए:

<!-- Resources on other origins must be CORS-enabled. -->
<link rel="import" href="http://example.com/elements.html">

सुविधा की पहचान और सहायता

यह देखने के लिए कि सहायता पाने के लिए, <link> एलिमेंट में .import मौजूद है या नहीं:

function supportsImports() {
    return 'import' in document.createElement('link');
}

if (supportsImports()) {
    // Good to go!
} else {
    // Use other libraries/require systems to load files.
}

यह सुविधा ब्राउज़र पर काम करती है. यह अभी शुरुआती दिनों में है. Chrome 31, वह पहला ब्राउज़र था जिसने लागू करने की प्रोसेस को देखा था. हालांकि, अन्य ब्राउज़र वेंडर यह देखने के लिए इंतज़ार कर रहे हैं कि ES मॉड्यूल कैसे काम करते हैं. हालांकि, दूसरे ब्राउज़र के लिए webcomps.js पॉलीफ़िल तब तक अच्छा काम करता है, जब तक चीज़ों को बड़े पैमाने पर इस्तेमाल नहीं किया जाता.

संसाधनों को इकट्ठा करना

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

इसका एक उदाहरण बूटस्ट्रैप है. बूटस्ट्रैप में अलग-अलग फ़ाइलें (bootstrap.css,boostrap.js, Font) होती हैं. इसके प्लगिन के लिए JQuery की ज़रूरत होती है और इसमें मार्कअप के उदाहरण होते हैं. डेवलपर को ज़्यादा विकल्प पसंद हैं. इसकी मदद से, वे फ़्रेमवर्क के उन हिस्सों में खरीदारी कर पाते हैं जिनका वे इस्तेमाल करना चाहते हैं. इसलिए, मेरा मानना है कि आपका सामान्य JoeDeveloperTM आसान रास्ता अपनाता है और बूटस्ट्रैप को डाउनलोड करता है.

इंपोर्ट करने से बूटस्ट्रैप जैसे काम का बहुत फ़ायदा मिलता है. मैं आपको पेश करता हूं, बूटस्ट्रैप लोड करने का भविष्य:

<head>
    <link rel="import" href="bootstrap.html">
</head>

उपयोगकर्ता सिर्फ़ एचटीएमएल इंपोर्ट का लिंक लोड करते हैं. उन्हें फ़ाइलों के स्कैटर शॉट से झगड़ने की ज़रूरत नहीं है. इसके बजाय, बूटस्ट्रैप की पूरी जानकारी को एक इंपोर्ट में, बूटस्ट्रैप.html में मैनेज कर दिया जाता है.

<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="fonts.css">
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="bootstrap-tooltip.js"></script>
<script src="bootstrap-dropdown.js"></script>
...

<!-- scaffolding markup -->
<template>
    ...
</template>

इसे रहने दो. यह काफ़ी दिलचस्प है.

लोड/गड़बड़ी वाले इवेंट

इंपोर्ट के लोड होने पर <link> एलिमेंट, load इवेंट को ट्रिगर करता है. साथ ही, इंपोर्ट पूरा न होने पर onerror को ट्रिगर करता है (उदाहरण के लिए, रिसॉर्स 404).

इंपोर्ट तुरंत लोड होने की कोशिश करते हैं. सिर दर्द से बचने का एक आसान तरीका है onload/onerror एट्रिब्यूट का इस्तेमाल करना:

<script>
    function handleLoad(e) {
    console.log('Loaded import: ' + e.target.href);
    }
    function handleError(e) {
    console.log('Error loading import: ' + e.target.href);
    }
</script>

<link rel="import" href="file.html"
        onload="handleLoad(event)" onerror="handleError(event)">

इसके अलावा, अगर डाइनैमिक तौर पर इंपोर्ट सेट किया जा रहा है, तो:

var link = document.createElement('link');
link.rel = 'import';
// link.setAttribute('async', ''); // make it async!
link.href = 'file.html';
link.onload = function(e) {...};
link.onerror = function(e) {...};
document.head.appendChild(link);

कॉन्टेंट का इस्तेमाल करना

किसी पेज पर इंपोर्ट शामिल करने का मतलब यह नहीं है कि "उस फ़ाइल का कॉन्टेंट यहां रखें". इसका मतलब है "पार्सर, इस दस्तावेज़ को फ़ेच करो, ताकि मैं इसका इस्तेमाल कर सकूं". कॉन्टेंट का इस्तेमाल करने के लिए, आपको कोई कार्रवाई करनी होगी और स्क्रिप्ट लिखनी होगी.

aha! का अहम पल यह महसूस करता है कि इंपोर्ट सिर्फ़ एक दस्तावेज़ है. इंपोर्ट किए गए कॉन्टेंट को इंपोर्ट का दस्तावेज़ कहा जाता है. आप स्टैंडर्ड DOM एपीआई का इस्तेमाल करके, इंपोर्ट के समय में बदलाव कर सकते हैं!

link.import

इंपोर्ट किए गए किसी कॉन्टेंट को ऐक्सेस करने के लिए, लिंक एलिमेंट की .import प्रॉपर्टी का इस्तेमाल करें:

var content = document.querySelector('link[rel="import"]').import;

link.import, इन शर्तों के तहत null है:

  • इस ब्राउज़र में, एचटीएमएल इंपोर्ट करने की सुविधा काम नहीं करती.
  • <link> के पास rel="import" नहीं है.
  • <link> को डीओएम में नहीं जोड़ा गया है.
  • <link> को DOM से हटा दिया गया है.
  • संसाधन में सीओआरएस की सुविधा चालू नहीं है.

पूरा उदाहरण

मान लें कि warnings.html में शामिल है:

<div class="warning">
    <style>
    h3 {
        color: red !important;
    }
    </style>
    <h3>Warning!
    <p>This page is under construction
</div>

<div class="outdated">
    <h3>Heads up!
    <p>This content may be out of date
</div>

इंपोर्ट करने वाले लोग इस दस्तावेज़ के किसी खास हिस्से को पा सकते हैं और अपने पेज में उसका क्लोन बना सकते हैं:

<head>
    <link rel="import" href="warnings.html">
</head>
<body>
    ...
    <script>
    var link = document.querySelector('link[rel="import"]');
    var content = link.import;

    // Grab DOM from warning.html's document.
    var el = content.querySelector('.warning');

    document.body.appendChild(el.cloneNode(true));
    </script>
</body>

इंपोर्ट में स्क्रिप्टिंग

इंपोर्ट किए गए दस्तावेज़, मुख्य दस्तावेज़ में नहीं हैं. ये डिवाइस, इस काम से सैटलाइट की तरह जुड़े हुए हैं. हालांकि, मुख्य दस्तावेज़ पर ही इंपोर्ट होने के बावजूद, इंपोर्ट की गई फ़ाइल मुख्य पेज पर काम कर सकती है. इंपोर्ट अपने खुद के DOM और/या उसे इंपोर्ट करने वाले पेज के DOM को ऐक्सेस कर सकता है:

उदाहरण -Import.html जो अपनी एक स्टाइलशीट को मुख्य पेज पर जोड़ता है

<link rel="stylesheet" href="http://www.example.com/styles.css">
<link rel="stylesheet" href="http://www.example.com/styles2.css">

<style>
/* Note: <style> in an import apply to the main
    document by default. That is, style tags don't need to be
    explicitly added to the main document. */
#somecontainer {
color: blue;
}
</style>
...

<script>
// importDoc references this import's document
var importDoc = document.currentScript.ownerDocument;

// mainDoc references the main document (the page that's importing us)
var mainDoc = document;

// Grab the first stylesheet from this import, clone it,
// and append it to the importing document.
    var styles = importDoc.querySelector('link[rel="stylesheet"]');
    mainDoc.head.appendChild(styles.cloneNode(true));
</script>

ध्यान दें कि यहां क्या हो रहा है. इंपोर्ट की स्क्रिप्ट में, इंपोर्ट किए गए दस्तावेज़ (document.currentScript.ownerDocument) को शामिल किया गया है. साथ ही, उस दस्तावेज़ के कुछ हिस्से को इंपोर्ट करने वाले पेज (mainDoc.head.appendChild(...)) से जोड़ा गया है. अगर आप चाहें, तो बहुत ही आसान है.

इंपोर्ट में JavaScript के नियम:

  • इंपोर्ट में स्क्रिप्ट को उस विंडो के हिसाब से एक्ज़ीक्यूट किया जाता है जिसमें इंपोर्ट किया जा रहा document शामिल है. इसलिए, window.document मुख्य पेज के दस्तावेज़ का है. इसके दो काम के कोरोलेरी हैं:
    • इंपोर्ट में तय किए गए फ़ंक्शन, window को खत्म होते हैं.
    • आपको इंपोर्ट के <script> ब्लॉक को मुख्य पेज में जोड़ने जैसा कोई मुश्किल काम नहीं करना होगा. फिर से, स्क्रिप्ट चलाई जाती है.
  • इंपोर्ट करने पर, मुख्य पेज को पार्स करने से नहीं रोका जाता. हालांकि, उनमें मौजूद स्क्रिप्ट एक क्रम में प्रोसेस की जाती हैं. इसका मतलब है कि आपको स्क्रिप्ट के सही क्रम को बनाए रखते हुए, डेफ़र जैसा व्यवहार मिलता है. इस बारे में यहां ज़्यादा जानकारी दी गई है.

वेब कॉम्पोनेंट डिलीवर करना

एचटीएमएल इंपोर्ट का डिज़ाइन, वेब पर फिर से इस्तेमाल किए जा सकने वाले कॉन्टेंट को लोड करने में मदद करता है. खास तौर पर, यह वेब कॉम्पोनेंट को डिस्ट्रिब्यूट करने का एक आदर्श तरीका है. बुनियादी एचटीएमएल <template> से लेकर शैडो DOM वाले कस्टम एलिमेंट तक सब कुछ [1, 2, 3]. जब इन टेक्नोलॉजी का एक साथ इस्तेमाल किया जाता है, तो वेब कॉम्पोनेंट के लिए इंपोर्ट, #include बन जाता है.

टेंप्लेट शामिल हैं

एचटीएमएल टेंप्लेट एलिमेंट, एचटीएमएल इंपोर्ट के लिए बिलकुल सही है. <template>, इंपोर्ट करने वाले ऐप्लिकेशन के लिए मार्कअप के सेक्शन को व्यवस्थित करने का सबसे अच्छा तरीका है, ताकि इसे अपनी पसंद के हिसाब से इस्तेमाल किया जा सके. कॉन्टेंट को <template> में रैप करने से, आपको उसका इस्तेमाल न करने का एक और फ़ायदा मिलता है. इसका मतलब है कि जब तक टेंप्लेट को DOM में नहीं जोड़ा जाता, तब तक स्क्रिप्ट नहीं चलती हैं). ज़बरदस्त!

import.html

<template>
    <h1>Hello World!</h1>
    <!-- Img is not requested until the <template> goes live. -->
    <img src="world.png">
    <script>alert("Executed when the template is activated.");</script>
</template>
index.html

<head>
    <link rel="import" href="import.html">
</head>
<body>
    <div id="container"></div>
    <script>
    var link = document.querySelector('link[rel="import"]');

    // Clone the <template> in the import.
    var template = link.import.querySelector('template');
    var clone = document.importNode(template.content, true);

    document.querySelector('#container').appendChild(clone);
    </script>
</body>

कस्टम एलिमेंट रजिस्टर करना

कस्टम एलिमेंट एक और वेब कॉम्पोनेंट टेक्नोलॉजी है, जो एचटीएमएल इंपोर्ट के साथ अजीब तरीके से अच्छा काम करती है. इंपोर्ट से स्क्रिप्ट एक्ज़ीक्यूट हो सकती है, तो क्यों न अपने कस्टम एलिमेंट को परिभाषित + रजिस्टर करें, ताकि उपयोगकर्ताओं को ऐसा न करना पड़े? इसे..." ऑटो-रजिस्ट्रेशन" कहते हैं.

elements.html

<script>
    // Define and register <say-hi>.
    var proto = Object.create(HTMLElement.prototype);

    proto.createdCallback = function() {
    this.innerHTML = 'Hello, <b>' +
                        (this.getAttribute('name') || '?') + '</b>';
    };

    document.registerElement('say-hi', {prototype: proto});
</script>

<template id="t">
    <style>
    ::content > * {
        color: red;
    }
    </style>
    <span>I'm a shadow-element using Shadow DOM!</span>
    <content></content>
</template>

<script>
    (function() {
    var importDoc = document.currentScript.ownerDocument; // importee

    // Define and register <shadow-element>
    // that uses Shadow DOM and a template.
    var proto2 = Object.create(HTMLElement.prototype);

    proto2.createdCallback = function() {
        // get template in import
        var template = importDoc.querySelector('#t');

        // import template into
        var clone = document.importNode(template.content, true);

        var root = this.createShadowRoot();
        root.appendChild(clone);
    };

    document.registerElement('shadow-element', {prototype: proto2});
    })();
</script>

इस इंपोर्ट से, दो एलिमेंट, <say-hi> और <shadow-element> के बारे में जानकारी मिलती है और रजिस्ट्रेशन होता है. पहला कॉलम एक बेसिक कस्टम एलिमेंट दिखाता है, जो खुद को इंपोर्ट में रजिस्टर करता है. दूसरे उदाहरण में, ऐसे कस्टम एलिमेंट को लागू करने का तरीका बताया गया है जो <template> से शैडो डीओएम बनाता है और खुद को रजिस्टर करता है.

एचटीएमएल इंपोर्ट में कस्टम एलिमेंट रजिस्टर करने के बारे में सबसे अच्छी बात यह है कि इंपोर्टर सिर्फ़ अपने पेज पर आपके एलिमेंट के बारे में जानकारी देता है. किसी वायरिंग की ज़रूरत नहीं है.

index.html

<head>
    <link rel="import" href="elements.html">
</head>
<body>
    <say-hi name="Eric"></say-hi>
    <shadow-element>
    <div>( I'm in the light dom )</div>
    </shadow-element>
</body>

मेरी राय में, सिर्फ़ यह वर्कफ़्लो एचटीएमएल इंपोर्ट को वेब कॉम्पोनेंट शेयर करने का एक आदर्श तरीका बनाता है.

डिपेंडेंसी और सब-इंपोर्ट मैनेज करना

सब-इंपोर्ट

एक इंपोर्ट को दूसरा इंपोर्ट करना मददगार हो सकता है. उदाहरण के लिए, अगर आपको किसी दूसरे कॉम्पोनेंट का फिर से इस्तेमाल करना है या उसे बढ़ाना है, तो अन्य एलिमेंट को लोड करने के लिए इंपोर्ट का इस्तेमाल करें.

नीचे पॉलीमर का एक सही उदाहरण दिया गया है. यह एक नया टैब कॉम्पोनेंट (<paper-tabs>) है, जो लेआउट और सिलेक्टर कॉम्पोनेंट का फिर से इस्तेमाल करता है. डिपेंडेंसी को एचटीएमएल इंपोर्ट का इस्तेमाल करके मैनेज किया जाता है.

पेपर-tabs.html (सरल):

<link rel="import" href="iron-selector.html">
<link rel="import" href="classes/iron-flex-layout.html">

<dom-module id="paper-tabs">
    <template>
    <style>...</style>
    <iron-selector class="layout horizonta center">
        <content select="*"></content>
    </iron-selector>
    </template>
    <script>...</script>
</dom-module>

ऐप्लिकेशन डेवलपर इनका इस्तेमाल करके इस नए एलिमेंट को इंपोर्ट कर सकते हैं:

<link rel="import" href="paper-tabs.html">
<paper-tabs></paper-tabs>

आने वाले समय में जब <iron-selector2> का नया और बेहतर वर्शन आएगा, तो <iron-selector> को बदलकर तुरंत इस्तेमाल किया जा सकता है. इंपोर्ट और वेब कॉम्पोनेंट की वजह से आपके उपयोगकर्ताओं की संख्या बढ़ेगी.

डिपेंडेंसी मैनेजमेंट

हम सभी जानते हैं कि हर पेज पर एक से ज़्यादा बार JQuery लोड करने से गड़बड़ियां होती हैं. क्या यह समस्या, वेब कॉम्पोनेंट के लिए बड़ी समस्या नहीं है. ऐसा तब होता है, जब एक से ज़्यादा कॉम्पोनेंट एक ही लाइब्रेरी का इस्तेमाल करते हैं? अगर हम एचटीएमएल इंपोर्ट का इस्तेमाल करते हैं, तो ऐसा नहीं होगा! डिपेंडेंसी मैनेज करने के लिए, इनका इस्तेमाल किया जा सकता है.

लाइब्रेरी को एचटीएमएल इंपोर्ट में रैप करके, रिसॉर्स को अपने-आप डी-ड्यूप किया जाता है. दस्तावेज़ को सिर्फ़ एक बार पार्स किया गया है. स्क्रिप्ट सिर्फ़ एक बार एक्ज़ीक्यूट की जाती हैं. उदाहरण के तौर पर, मान लें कि आपने jquery.html ऐसा इंपोर्ट तय किया है जो JQuery की कॉपी लोड करता है.

jquery.html

<script src="http://cdn.com/jquery.js"></script>

बाद के इंपोर्ट में इस इंपोर्ट का फिर से इस्तेमाल किया जा सकता है, जैसे कि:

import2.html

<link rel="import" href="jquery.html">
<div>Hello, I'm import 2</div>
ajax-element.html

<link rel="import" href="jquery.html">
<link rel="import" href="import2.html">

<script>
    var proto = Object.create(HTMLElement.prototype);

    proto.makeRequest = function(url, done) {
    return $.ajax(url).done(function() {
        done();
    });
    };

    document.registerElement('ajax-element', {prototype: proto});
</script>

अगर लाइब्रेरी की ज़रूरत है, तो मुख्य पेज पर भी jquery.html को शामिल किया जा सकता है:

<head>
    <link rel="import" href="jquery.html">
    <link rel="import" href="ajax-element.html">
</head>
<body>

...

<script>
    $(document).ready(function() {
    var el = document.createElement('ajax-element');
    el.makeRequest('http://example.com');
    });
</script>
</body>

jquery.html के कई अलग-अलग इंपोर्ट ट्री में शामिल होने के बावजूद, इसके दस्तावेज़ को ब्राउज़र से सिर्फ़ एक बार फ़ेच और प्रोसेस किया जाता है. नेटवर्क पैनल की जांच करने से यह साबित हो जाता है:

jquery.html का एक बार अनुरोध किया गया
jquery.html का अनुरोध एक बार किया गया है

प्रदर्शन संबंधी विचार

एचटीएमएल इंपोर्ट पूरी तरह से शानदार होते हैं, लेकिन किसी भी नई वेब टेक्नोलॉजी की तरह ही, आपको उनका इस्तेमाल समझदारी से करना चाहिए. वेब डेवलपमेंट के सबसे सही तरीके अब भी सही हैं. इन बातों का ध्यान रखें.

इंपोर्ट जोड़ें

नेटवर्क अनुरोधों को कम करना हमेशा ज़रूरी होता है. अगर आपके पास कई टॉप-लेवल इंपोर्ट लिंक हैं, तो उन्हें एक ही संसाधन में मिलाने और उस फ़ाइल को इंपोर्ट करने पर विचार करें!

Vulcanize, पॉलीमर टीम का एक npm बिल्ड टूल है, जो एचटीएमएल इंपोर्ट के सेट को बार-बार एक ही फ़ाइल में एक जैसा करता है. इसे वेब कॉम्पोनेंट के लिए स्ट्रिंग जोड़ने की प्रोसेस के तौर पर देखें.

इंपोर्ट से, ब्राउज़र को कैश मेमोरी में सेव करने की सुविधा

कई लोग यह भूल जाते हैं कि ब्राउज़र के नेटवर्किंग स्टैक को पिछले कई सालों में बहुत बारीकी से ट्यून किया गया है. इंपोर्ट (और सब-इंपोर्ट) में भी इस लॉजिक का इस्तेमाल किया जाता है. http://cdn.com/bootstrap.html इंपोर्ट में सब-संसाधन हो सकते हैं, लेकिन उन्हें कैश मेमोरी में सेव किया जाएगा.

कॉन्टेंट सिर्फ़ तब काम आता है, जब आपने उसे जोड़ा हो

जब तक आप उसकी सेवाओं को कॉल न करें, तब तक कॉन्टेंट को बेअसर मानें. सामान्य, डाइनैमिक रूप से बनाई गई स्टाइलशीट लें:

var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'styles.css';

जब तक link को DOM में नहीं जोड़ा जाता, तब तक ब्राउज़र Style.css का अनुरोध नहीं करेगा:

document.head.appendChild(link); // browser requests styles.css

डाइनैमिक तरीके से बनाए गए मार्कअप का एक और उदाहरण है:

var h2 = document.createElement('h2');
h2.textContent = 'Booyah!';

जब तक आप इसे DOM में नहीं जोड़ते, तब तक h2 का कोई मतलब नहीं होता.

इंपोर्ट के दस्तावेज़ पर भी यही सिद्धांत लागू होता है. जब तक आप इसकी सामग्री को DOM में नहीं जोड़ते, तब तक यह काम नहीं करता. असल में, इंपोर्ट दस्तावेज़ में सीधे तौर पर सिर्फ़ <script> ही "काम करता है". इंपोर्ट में स्क्रिप्टिंग देखें.

एक साथ काम नहीं करने वाली प्रोसेस से लोड होने के लिए ऑप्टिमाइज़ किया जा रहा है

रेंडरिंग को ब्लॉक करके इंपोर्ट करता है

मुख्य पेज की रेंडरिंग को इंपोर्ट होने से रोकता है. यह <link rel="stylesheet"> जैसा है. ब्राउज़र, स्टाइलशीट पर सबसे पहले रेंडर होने से रोकता है. इसकी वजह एफ़ओयूसी को कम करना है. इंपोर्ट किए गए काम इसी तरह से काम करते हैं, क्योंकि उनमें स्टाइलशीट हो सकती हैं.

पूरी तरह से एसिंक्रोनस होने और पार्सर या रेंडरिंग को ब्लॉक न करने के लिए, async एट्रिब्यूट का इस्तेमाल करें:

<link rel="import" href="/path/to/import_that_takes_5secs.html" async>

एचटीएमएल इंपोर्ट के लिए async डिफ़ॉल्ट तौर पर इस्तेमाल नहीं होता है. ऐसा इसलिए है, क्योंकि इसके लिए डेवलपर को ज़्यादा काम करना पड़ता है. डिफ़ॉल्ट रूप से सिंक्रोनस का मतलब है कि जिन एचटीएमएल इंपोर्ट में कस्टम एलिमेंट परिभाषाएं होती हैं वे क्रम में लोड और अपग्रेड होने की गारंटी देते हैं. एक जैसी दुनिया में, डेवलपर को अपने डांस के समय को खुद ही मैनेज करना होगा और अपने कैंपेन के टाइमिंग को खुद ही अपग्रेड करना होगा.

डाइनैमिक तौर पर, एक साथ काम नहीं करने वाली प्रोसेस से इंपोर्ट किए जा सकते हैं:

var l = document.createElement('link');
l.rel = 'import';
l.href = 'elements.html';
l.setAttribute('async', '');
l.onload = function(e) { ... };

इंपोर्ट किए गए आइटम, पार्स करने की सुविधा को ब्लॉक नहीं करते

इंपोर्ट करने पर मुख्य पेज को पार्स करने से नहीं रोका जाता. इंपोर्ट में मौजूद स्क्रिप्ट, क्रम में प्रोसेस की जाती हैं. हालांकि, ये इंपोर्ट करने वाले पेज को ब्लॉक नहीं करती. इसका मतलब है कि आपको स्क्रिप्ट के सही क्रम को बनाए रखते हुए, डेफ़र जैसा व्यवहार मिलता है. अपने इंपोर्ट को <head> में रखने का एक फ़ायदा यह है कि इससे पार्सर, कॉन्टेंट पर जल्द से जल्द काम करना शुरू कर देता है. हालांकि, मुख्य दस्तावेज़ में <script> को याद रखना ज़रूरी है फिर भी पेज को ब्लॉक करना जारी रहेगा. इंपोर्ट करने के बाद, पहला <script> पेज रेंडरिंग को ब्लॉक कर देगा. ऐसा इसलिए, क्योंकि किसी इंपोर्ट में ऐसी स्क्रिप्ट हो सकती है जिसे मुख्य पेज में स्क्रिप्ट से पहले लागू करना ज़रूरी है.

<head>
    <link rel="import" href="/path/to/import_that_takes_5secs.html">
    <script>console.log('I block page rendering');</script>
</head>

आपके ऐप्लिकेशन के स्ट्रक्चर और इस्तेमाल के उदाहरण के आधार पर, एक साथ काम नहीं करने वाली प्रोसेस को ऑप्टिमाइज़ करने के कई तरीके हैं. नीचे दी गई तकनीकों का इस्तेमाल करके, मुख्य पेज की रेंडरिंग को ब्लॉक किया जा सकता है.

स्थिति #1 (पसंदीदा): आपके पास <head> में कोई स्क्रिप्ट नहीं है या <body> में कोई स्क्रिप्ट नहीं है

मेरा सुझाव है कि <script> को शामिल करें. इसलिए, इंपोर्ट किए गए डेटा को तुरंत फ़ॉलो करने से बचें. गेम में स्क्रिप्ट को देर से दूसरी जगह ले जाएं...लेकिन आप तो पहले से ही सही तरीका अपना रहे हैं, है न!? ;)

यहां एक उदाहरण दिया गया है:

<head>
    <link rel="import" href="/path/to/import.html">
    <link rel="import" href="/path/to/import2.html">
    <!-- avoid including script -->
</head>
<body>
    <!-- avoid including script -->

    <div id="container"></div>

    <!-- avoid including script -->
    ...

    <script>
    // Other scripts n' stuff.

    // Bring in the import content.
    var link = document.querySelector('link[rel="import"]');
    var post = link.import.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
    </script>
</body>

सभी चीज़ें नीचे की तरफ़ होती हैं.

स्थिति 1.5: इंपोर्ट अपने-आप जुड़ जाता है

दूसरा विकल्प यह है कि इंपोर्ट में अपना कॉन्टेंट जोड़ा जा सकता है. अगर इंपोर्ट करने वाला व्यक्ति ऐप्लिकेशन डेवलपर से फ़ॉलो करने के लिए अनुबंध तय करता है, तो इंपोर्ट खुद को मुख्य पेज के किसी हिस्से में जोड़ सकता है:

import.html:

<div id="blog-post">...</div>
<script>
    var me = document.currentScript.ownerDocument;
    var post = me.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
</script>
index.html

<head>
    <link rel="import" href="/path/to/import.html">
</head>
<body>
    <!-- no need for script. the import takes care of things -->
</body>

स्थिति #2: आपके पास <head> में स्क्रिप्ट है या <body> में अंडरलाइन की गई है

अगर आपने किसी ऐसे डिवाइस को इंपोर्ट किया है जिसे लोड होने में ज़्यादा समय लगता है, तो पेज पर उसे फ़ॉलो करने वाला पहला <script>, पेज को रेंडर होने से रोक देगा. उदाहरण के लिए, Google Analytics, आपको <head> में ट्रैकिंग कोड डालने का सुझाव देता है. अगर <head> में <script> डालने से बचा नहीं जा सकता, तो डाइनैमिक तौर पर इंपोर्ट जोड़ने से पेज ब्लॉक नहीं होगा:

<head>
    <script>
    function addImportLink(url) {
        var link = document.createElement('link');
        link.rel = 'import';
        link.href = url;
        link.onload = function(e) {
        var post = this.import.querySelector('#blog-post');

        var container = document.querySelector('#container');
        container.appendChild(post.cloneNode(true));
        };
        document.head.appendChild(link);
    }

    addImportLink('/path/to/import.html'); // Import is added early :)
    </script>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...
</body>

इसके अलावा, इंपोर्ट को <body> के आखिर में जोड़ें:

<head>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...

    <script>
    function addImportLink(url) { ... }

    addImportLink('/path/to/import.html'); // Import is added very late :(
    </script>
</body>

याद रखने वाली बातें

  • इंपोर्ट का mimetype text/html है.

  • दूसरे ऑरिजिन के रिसॉर्स, सीओआरएस की सुविधा वाले होने चाहिए.

  • एक ही यूआरएल से किए गए इंपोर्ट, एक बार फ़ेच और पार्स किए जाते हैं. इसका मतलब है कि किसी इंपोर्ट में स्क्रिप्ट सिर्फ़ पहली बार इंपोर्ट देखे जाने पर ही एक्ज़ीक्यूट की जाती है.

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

  • इंपोर्ट लिंक का मतलब यह नहीं है कि "#कॉन्टेंट को यहां शामिल करें". इसका मतलब है "पार्सर, इस दस्तावेज़ को फ़ेच करो, ताकि मैं इसे बाद में इस्तेमाल कर सकूं". स्क्रिप्ट, इंपोर्ट के समय काम करती हैं. हालांकि, स्टाइलशीट, मार्कअप, और अन्य संसाधनों को मुख्य पेज पर साफ़ तौर पर जोड़ना ज़रूरी है. ध्यान दें, <style> को अलग से जोड़ने की ज़रूरत नहीं है. यह एचटीएमएल इंपोर्ट और <iframe> के बीच एक बड़ा अंतर है, जो कहता है कि "इस कॉन्टेंट को यहां लोड और रेंडर करें".

नतीजा

एचटीएमएल इंपोर्ट की मदद से, एचटीएमएल/CSS/JS को एक संसाधन के रूप में बंडल किया जा सकता है. हालांकि यह आइडिया अपने-आप काम का है, लेकिन वेब कॉम्पोनेंट की दुनिया में यह बेहद असरदार साबित हो जाता है. डेवलपर, <link rel="import"> के ज़रिए डिलीवर किए गए कॉम्पोनेंट बना सकते हैं, ताकि दूसरे लोग इनका इस्तेमाल कर सकें और अपने ऐप्लिकेशन में ला सकें. ये कॉम्पोनेंट फिर से इस्तेमाल किए जा सकते हैं.

एचटीएमएल इंपोर्ट एक आसान कॉन्सेप्ट है, लेकिन इस प्लैटफ़ॉर्म के इस्तेमाल के कई दिलचस्प उदाहरण उपलब्ध हैं.

इस्तेमाल के उदाहरण

  • मिलते-जुलते एचटीएमएल/सीएसएस/JS को एक बंडल के तौर पर डिस्ट्रिब्यूट करें. सैद्धांतिक तौर पर, पूरे वेब ऐप्लिकेशन को किसी दूसरे वेब ऐप्लिकेशन में इंपोर्ट किया जा सकता है.
  • कोड संगठन - कॉन्सेप्ट को सही तरीके से अलग-अलग फ़ाइलों में बांटें. इससे मॉड्यूलरिटी और फिर से इस्तेमाल करने के लिए बढ़ावा मिलता है**.
  • एक या ज़्यादा कस्टम एलिमेंट परिभाषाएं डिलीवर करें. इंपोर्ट का इस्तेमाल register और उन्हें किसी ऐप्लिकेशन में शामिल करने के लिए किया जा सकता है. ऐसा करने से, यह सॉफ़्टवेयर के अच्छे पैटर्न का इस्तेमाल करता है. साथ ही, यह एलिमेंट के इंटरफ़ेस/परिभाषा को इस्तेमाल करने के तरीके से अलग रखता है.
  • डिपेंडेंसी मैनेज करें - संसाधनों के डुप्लीकेट वर्शन अपने-आप हटा दिए जाते हैं.
  • चंक स्क्रिप्ट - इंपोर्ट से पहले, एक बड़े साइज़ की JS लाइब्रेरी को चलाना शुरू करने के लिए, अपनी फ़ाइल को पूरी तरह से पार्स करना होगा. हालांकि, यह प्रोसेस धीमी थी. इंपोर्ट की मदद से, हिस्से A के पार्स होते ही लाइब्रेरी काम करना शुरू कर सकती है. इंतज़ार का समय कम!
// TODO: DevSite - Code sample removed as it used inline event handlers
  • एचटीएमएल पार्स करना - पहली बार जब ब्राउज़र एक साथ दो (या ज़्यादा) एचटीएमएल पार्सर चला पाया हो.

  • यह इंपोर्ट टारगेट को बदलकर, किसी ऐप्लिकेशन में डीबग और गैर-डीबग मोड के बीच स्विच करने की सुविधा देता है. आपके ऐप्लिकेशन को यह जानने की ज़रूरत नहीं है कि इंपोर्ट टारगेट, बंडल/कंपोज़ किया गया रिसॉर्स है या इंपोर्ट ट्री है.