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

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

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

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

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

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

शुरू करना

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

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

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

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

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

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

सुविधा का पता लगाना और सहायता

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

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

संसाधनों को बंडल करना

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

असल दुनिया का उदाहरण Bootstrap है. Bootstrap में अलग-अलग फ़ाइलें (bootstrap.css, bootstrap.js, फ़ॉन्ट) शामिल होती हैं. इसके प्लग इन के लिए, JQuery की ज़रूरत होती है. साथ ही, यह मार्कअप के उदाहरण भी उपलब्ध कराता है. डेवलपर की सुविधाओं में हर तरह के विकल्प शामिल होते हैं. इससे वे फ़्रेमवर्क के उन हिस्सों में खरीदारी कर पाते हैं जिनका इस्तेमाल करना है. हालांकि, मेरा मानना है कि आम तौर पर, JoeDeveloper™ आसान तरीका अपनाता है और Bootstrap का पूरा वर्शन डाउनलोड करता है.

Bootstrap जैसी चीज़ों के लिए, इंपोर्ट का इस्तेमाल करना बहुत फ़ायदेमंद होता है. हम आपको Bootstrap को लोड करने का नया तरीका बताते हैं:

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

उपयोगकर्ता, एचटीएमएल इंपोर्ट लिंक को आसानी से लोड कर सकते हैं. उन्हें अलग-अलग जगहों पर मौजूद फ़ाइलों को ढूंढने की ज़रूरत नहीं पड़ती. इसके बजाय, Bootstrap को पूरी तरह से मैनेज किया जाता है और इसे इंपोर्ट, bootstrap.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 API का इस्तेमाल करके, इंपोर्ट के कॉन्फ़िगरेशन में बदलाव किया जा सकता है!

link.import

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

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

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

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

पूरा उदाहरण

मान लें कि 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>

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

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

उदाहरण - export.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> से लेकर, Shadow 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> से शैडो DOM बनाता है और फिर खुद को रजिस्टर करता है.

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

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>

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

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

सब-इंपोर्ट

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

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

paper-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 का अनुरोध एक बार किया गया है

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

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

इंपोर्ट को जोड़ना

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

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

इंपोर्ट के लिए ब्राउज़र कैश मेमोरी का इस्तेमाल करना

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

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

जब तक कॉन्टेंट का इस्तेमाल नहीं किया जाता, तब तक उसे निष्क्रिय मानें. डाइनैमिक तौर पर बनाई गई सामान्य स्टाइलशीट लें:

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

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

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

डाइनैमिक तौर पर जनरेट होने वाले मार्कअप का एक और उदाहरण:

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

जब तक 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> में ट्रैकिंग कोड डालें. अगर <script> को <head> में डालने से बचा नहीं जा सकता, तो डाइनैमिक तौर पर इंपोर्ट जोड़ने से पेज ब्लॉक नहीं होगा:

<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>

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

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

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

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

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

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

नतीजा

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

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

उपयोग के उदाहरण

// TODO: DevSite - Code sample removed as it used inline event handlers
  • एचटीएमएल को एक साथ कई प्रोसेस में पार्स करता है - पहली बार ब्राउज़र, दो या उससे ज़्यादा एचटीएमएल पार्सर को एक साथ चला पाया है.

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