वेब के लिए शामिल करें
इंपोर्ट क्यों करना चाहिए?
इस बारे में सोचें कि वेब पर अलग-अलग तरह के संसाधन कैसे लोड किए जाते हैं. JS के लिए, हमारे पास <script src>
है. सीएसएस के लिए, <link rel="stylesheet">
का इस्तेमाल किया जा सकता है. इमेज के लिए, यह <img>
है. वीडियो में <video>
है. ऑडियो, <audio>
… सीधे मुद्दे पर आएं! वेब के ज़्यादातर कॉन्टेंट को लोड करने का एक आसान और साफ़ तौर पर बताया गया तरीका होता है. हालांकि, एचटीएमएल के लिए ऐसा नहीं है. आपके पास ये विकल्प हैं:
<iframe>
- यह तरीका आज़माया जा चुका है और यह कारगर है. हालांकि, यह तरीका भारी है. iframe का कॉन्टेंट, आपके पेज से पूरी तरह से अलग होता है. यह सुविधा ज़्यादातर मामलों में बेहतरीन होती है, लेकिन इससे कुछ और समस्याएं भी आती हैं. जैसे, फ़्रेम के साइज़ को उसके कॉन्टेंट के हिसाब से छोटा करना मुश्किल होता है. साथ ही, स्क्रिप्ट में/स्क्रिप्ट से बाहर निकलना बहुत मुश्किल होता है. साथ ही, इसे स्टाइल करना लगभग असंभव होता है.- AJAX - मुझे
xhr.responseType="document"
पसंद है, लेकिन क्या आपका कहना है कि एचटीएमएल लोड करने के लिए, मुझे JS की ज़रूरत है? ऐसा नहीं लगता. - 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 Modules का इस्तेमाल किया गया था. हालांकि, दूसरे ब्राउज़र वेंडर यह देखना चाहते हैं कि ES Modules का इस्तेमाल कैसे किया जाता है. हालांकि, जब तक वेबकॉम्पोनेंट का इस्तेमाल सभी ब्राउज़र पर नहीं किया जा सकता, तब तक अन्य ब्राउज़र के लिए 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>
इंपोर्ट में स्क्रिप्टिंग
इंपोर्ट, मुख्य दस्तावेज़ में नहीं हैं. वे इसके सैटलाइट हैं. हालांकि, मुख्य दस्तावेज़ सबसे अहम होने के बावजूद, आपका इंपोर्ट अब भी मुख्य पेज पर काम कर सकता है. इंपोर्ट, अपने डीओएम और/या उसे इंपोर्ट करने वाले पेज के डीओएम को ऐक्सेस कर सकता है:
उदाहरण - 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>
ब्लॉक जोड़ना. फिर से, स्क्रिप्ट लागू हो जाती है.
- इंपोर्ट में तय किए गए फ़ंक्शन,
- इंपोर्ट करने से, मुख्य पेज को पार्स करने की प्रोसेस में रुकावट नहीं आती. हालांकि, इनमें मौजूद स्क्रिप्ट को क्रम से प्रोसेस किया जाता है. इसका मतलब है कि स्क्रिप्ट के सही क्रम को बनाए रखते हुए, आपको 'देर से चलाएं' सुविधा जैसा व्यवहार मिलता है. इस बारे में ज़्यादा जानकारी यहां दी गई है.
वेब कॉम्पोनेंट डिलीवर करना
एचटीएमएल इंपोर्ट के डिज़ाइन की मदद से, वेब पर फिर से इस्तेमाल किए जा सकने वाले कॉन्टेंट को आसानी से लोड किया जा सकता है. खास तौर पर, यह वेब कॉम्पोनेंट को डिस्ट्रिब्यूट करने का एक बेहतरीन तरीका है. इसमें, Shadow DOM [1, 2, 3] के साथ, बुनियादी एचटीएमएल <template>
से लेकर पूरी तरह से तैयार कस्टम एलिमेंट तक सब कुछ शामिल है. जब इन टेक्नोलॉजी का एक साथ इस्तेमाल किया जाता है, तो वेब कॉम्पोनेंट के लिए इंपोर्ट, #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 को कई अलग-अलग इंपोर्ट ट्री में शामिल करने के बावजूद, ब्राउज़र इसका दस्तावेज़ सिर्फ़ एक बार फ़ेच और प्रोसेस करता है. नेटवर्क पैनल की जांच करने से यह पता चलता है:
प्रदर्शन संबंधी विचार
एचटीएमएल इंपोर्ट बहुत शानदार हैं. हालांकि, किसी भी नई वेब टेक्नोलॉजी की तरह, आपको इनका इस्तेमाल समझदारी से करना चाहिए. वेब डेवलपमेंट के सबसे सही तरीके अब भी काम के हैं. यहां कुछ बातों का ध्यान रखें.
इंपोर्ट को जोड़ना
नेटवर्क अनुरोधों को कम करना हमेशा ज़रूरी होता है. अगर आपके पास कई टॉप-लेवल इंपोर्ट लिंक हैं, तो उन्हें एक ही संसाधन में जोड़कर उस फ़ाइल को इंपोर्ट करें!
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 में नहीं जोड़ा जाता.
इंपोर्ट किए जाने वाले दस्तावेज़ के लिए भी यही बात लागू होती है. जब तक इसके कॉन्टेंट को 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>
याद रखने वाली बातें
इंपोर्ट का mime टाइप
text/html
है.दूसरे ऑरिजिन के रिसॉर्स के लिए, सीओआरएस की सुविधा चालू होनी चाहिए.
एक ही यूआरएल से इंपोर्ट किए गए डेटा को एक बार ही वापस पाया और पार्स किया जाता है. इसका मतलब है कि इंपोर्ट में मौजूद स्क्रिप्ट, सिर्फ़ पहली बार इंपोर्ट को देखने पर ही लागू होती है.
इंपोर्ट की गई स्क्रिप्ट को क्रम से प्रोसेस किया जाता है. हालांकि, ये मुख्य दस्तावेज़ को पार्स करने की प्रोसेस को ब्लॉक नहीं करतीं.
इंपोर्ट लिंक का मतलब "#content को यहां शामिल करें" नहीं है. इसका मतलब है कि "पार्सर, इस दस्तावेज़ को फ़ेच करो, ताकि मैं इसका बाद में इस्तेमाल कर सकूं". इंपोर्ट के समय स्क्रिप्ट लागू हो जाती हैं, लेकिन स्टाइलशीट, मार्कअप, और अन्य रिसॉर्स को मुख्य पेज में साफ़ तौर पर जोड़ना ज़रूरी है. ध्यान दें,
<style>
को साफ़ तौर पर जोड़ने की ज़रूरत नहीं है. एचटीएमएल इंपोर्ट और<iframe>
के बीच यह एक बड़ा अंतर है. एचटीएमएल इंपोर्ट में, "इस कॉन्टेंट को यहां लोड और रेंडर करें" कहा जाता है.
नतीजा
एचटीएमएल इंपोर्ट की मदद से, एचटीएमएल/सीएसएस/JS को एक ही रिसॉर्स के तौर पर बंडल किया जा सकता है. यह आइडिया अपने-आप ही काम का है, लेकिन वेब कॉम्पोनेंट की दुनिया में यह बहुत ही असरदार हो जाता है. डेवलपर, फिर से इस्तेमाल किए जा सकने वाले कॉम्पोनेंट बना सकते हैं, ताकि दूसरे लोग उन्हें इस्तेमाल कर सकें और अपने ऐप्लिकेशन में शामिल कर सकें. ये कॉम्पोनेंट, <link rel="import">
के ज़रिए डिलीवर किए जाते हैं.
एचटीएमएल इंपोर्ट एक आसान कॉन्सेप्ट है. हालांकि, इससे प्लैटफ़ॉर्म के लिए कई दिलचस्प इस्तेमाल के उदाहरण मिलते हैं.
उपयोग के उदाहरण
- मिलते-जुलते एचटीएमएल/सीएसएस/JS को एक बंडल के तौर पर डिस्ट्रिब्यूट करें. सिद्धांत रूप से, किसी वेब ऐप्लिकेशन को किसी दूसरे वेब ऐप्लिकेशन में इंपोर्ट किया जा सकता है.
- कोड को व्यवस्थित करना - कॉन्सेप्ट को अलग-अलग फ़ाइलों में व्यवस्थित करना, ताकि उन्हें आसानी से फिर से इस्तेमाल किया जा सके और मॉड्यूलर बनाया जा सके**.
- एक या उससे ज़्यादा कस्टम एलिमेंट डेफ़िनिशन डिलीवर करें. इंपोर्ट का इस्तेमाल, एलिमेंट को register करने और उन्हें ऐप्लिकेशन में शामिल करने के लिए किया जा सकता है. यह अच्छे सॉफ़्टवेयर पैटर्न का इस्तेमाल करता है. इसमें एलिमेंट के इंटरफ़ेस/डेफ़िनिशन को, उसके इस्तेमाल से अलग रखा जाता है.
- डिपेंडेंसी मैनेज करना - रिसॉर्स अपने-आप डुप्लीकेट नहीं होते.
- चंक स्क्रिप्ट - इंपोर्ट करने से पहले, बड़ी साइज़ वाली जेएस लाइब्रेरी को चलाने के लिए, उसकी फ़ाइल को पूरी तरह से पार्स करना पड़ता था. यह प्रोसेस धीमी होती थी. इंपोर्ट की मदद से, चंक A को पार्स करने के बाद ही लाइब्रेरी काम करना शुरू कर सकती है. इंतज़ार का समय कम!
// TODO: DevSite - Code sample removed as it used inline event handlers
एचटीएमएल को एक साथ कई प्रोसेस में पार्स करता है - पहली बार ब्राउज़र, दो या उससे ज़्यादा एचटीएमएल पार्सर को एक साथ चला पाया है.
किसी ऐप्लिकेशन में, डीबग और नॉन-डीबग मोड के बीच स्विच करने की सुविधा चालू करता है. इसके लिए, इंपोर्ट टारगेट में बदलाव करना होता है. आपके ऐप्लिकेशन को यह जानने की ज़रूरत नहीं है कि इंपोर्ट टारगेट, बंडल किया गया/कंपाइल किया गया रिसॉर्स है या इंपोर्ट ट्री.