تضمين المحتوى على الويب
لماذا الاستيراد؟
فكِّر في كيفية تحميل أنواع مختلفة من الموارد على الويب. بالنسبة إلى JavaScript، لدينا <script src>
. بالنسبة إلى CSS، من المرجّح أن يكون <link rel="stylesheet">
هو الخيار المفضّل لديك. بالنسبة إلى الصور، تكون القيمة <img>
. يتضمّن الفيديو <video>
. الصوت، <audio>
… ادخل في صلب الموضوع. إنّ معظم محتوى الويب يتضمّن طريقة بسيطة وواضحة لتحميل نفسه. لا ينطبق ذلك على HTML. في ما يلي الخيارات المتاحة لك:
-
<iframe>
: أسلوب مجرّب وفعّال، ولكنه ثقيل. يظهر محتوى إطار iframe بالكامل في سياق منفصل عن صفحتك. على الرغم من أنّ هذه الميزة رائعة في معظم الأحيان، إلا أنّها تؤدي إلى ظهور تحديات إضافية (من الصعب تصغير حجم الإطار ليناسب المحتوى، ومن الصعب جدًا إنشاء نص برمجي للإطار أو الخروج منه، ومن شبه المستحيل تطبيق تنسيق عليه). - AJAX - أحبّ
xhr.responseType="document"
، ولكن هل أنت بحاجة إلى JavaScript لتحميل HTML؟ يبدو أنّ هناك مشكلة. - CrazyHacks™: مضمّنة في سلاسل، مخفية كتعليقات (مثل
<script type="text/html">
).
هل ترى المفارقة؟ إنّ محتوى الويب الأساسي، وهو HTML، يتطلّب أكبر قدر من الجهد للعمل معه. لحسن الحظ، تتوفّر مكونات الويب لمساعدتنا في استعادة المسار الصحيح.
الخطوات الأولى
عمليات استيراد HTML هي جزء من مجموعة مكونات الويب، وهي طريقة لتضمين مستندات HTML في مستندات HTML أخرى. ولا تقتصر على استخدام العلامات أيضًا. يمكن أن يتضمّن الاستيراد أيضًا ملف CSS أو JavaScript أو أي ملف آخر يمكن أن يحتوي عليه ملف .html
. بعبارة أخرى، تُعدّ عمليات الاستيراد أداة رائعة لتحميل محتوى HTML/CSS/JS ذي الصلة.
الأساسيات
يمكنك تضمين عملية استيراد في صفحتك من خلال تحديد <link rel="import">
:
<head>
<link rel="import" href="/path/to/imports/stuff.html">
</head>
يُطلَق على عنوان URL لعملية الاستيراد موقع استيراد. لتحميل محتوى من نطاق آخر، يجب تفعيل بروتوكول 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 بشكلٍ رائع إلى أن تصبح العناصر متوافقة على نطاق واسع.
تجميع الموارد
توفّر عمليات الاستيراد اصطلاحًا لتجميع HTML/CSS/JS (حتى عمليات استيراد HTML الأخرى) في ملف واحد مُرسَل. هذه ميزة أساسية، ولكنها قوية. إذا كنت بصدد إنشاء مظهر أو مكتبة أو كنت تريد فقط تقسيم تطبيقك إلى أجزاء منطقية، من الأفضل منح المستخدمين عنوان URL واحدًا. يمكنك حتى إرسال تطبيق كامل من خلال عملية استيراد. ننصحك بالتفكير في ذلك للحظة.
ومن الأمثلة على ذلك إطار عمل Bootstrap. تتألّف Bootstrap من ملفات فردية (bootstrap.css وbootstrap.js والخطوط)، وتتطلّب JQuery لإضافاتها، وتقدّم أمثلة على الترميز. يفضّل المطوّرون المرونة في اختيار الخطط. ويسمح لهم بالموافقة على أجزاء الإطار التي يريدون استخدامها. ومع ذلك، أراهن بأنّ المطوّر العادي سيختار الطريقة السهلة وينزّل كلّ Bootstrap.
تكون عمليات الاستيراد مفيدة جدًا في أدوات مثل Bootstrap. إليك مستقبل تحميل Bootstrap:
<head>
<link rel="import" href="bootstrap.html">
</head>
ما على المستخدمين سوى تحميل رابط استيراد HTML. ولن يحتاجوا إلى التعامل مع الملفات المتفرقة. بدلاً من ذلك، تتم إدارة 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 العادية.
link.import
للوصول إلى محتوى عملية الاستيراد، استخدِم السمة .import
لعنصر الرابط:
var content = document.querySelector('link[rel="import"]').import;
link.import
هي null
في حال استيفاء الشروط التالية:
- لا يتيح المتصفّح استخدام ميزة "استيراد HTML".
- لا يتوفّر لدى
<link>
rel="import"
. - لم تتم إضافة
<link>
إلى DOM. - تمت إزالة
<link>
من نموذج DOM. - المورد غير مفعَّل فيه سياسة مشاركة الموارد المتعدّدة المصادر (CORS).
مثال كامل
لنفترض أنّ 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>
الخاصة بالاستيراد بالصفحة الرئيسية. يتم تنفيذ النص البرمجي مرة أخرى.
- تنتهي الدوال المحدّدة في عملية استيراد في
- لا تحظر عمليات الاستيراد تحليل الصفحة الرئيسية. ومع ذلك، تتم معالجة النصوص البرمجية داخلها بالترتيب. وهذا يعني أنّك تحصل على سلوك مشابه لـ defer مع الحفاظ على ترتيب النص البرمجي الصحيح. يمكنك الاطّلاع على مزيد من المعلومات عن هذا الموضوع أدناه.
عرض مكوّنات الويب
يُعدّ تصميم عمليات استيراد HTML مناسبًا لتحميل محتوى قابل لإعادة الاستخدام على الويب. على وجه الخصوص، هي طريقة مثالية لتوزيع مكوّنات الويب. كل شيء، بدءًا من عناصر HTML <template>
الأساسية ووصولاً إلى العناصر المخصّصة الكاملة باستخدام Shadow DOM [1 و2 و3] عند استخدام هاتين التقنيتَين معًا، تصبح عمليات الاستيراد #include
لمكوّنات الويب.
بما في ذلك النماذج
يُعدّ عنصر نموذج HTML مناسبًا بشكلٍ طبيعي لاستيراد ملفات HTML. <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>
تسجيل العناصر المخصّصة
Custom Elements هي تقنية أخرى من مكونات الويب تتوافق بشكل جيد مع عمليات استيراد HTML. يمكن أن تنفِّذ عمليات الاستيراد نصوص برمجية، لذا لماذا لا تحدِّد عناصرك المخصّصة وتُسجِّلها كي لا يحتاج المستخدمون إلى ذلك؟ لنسمّيها "التسجيل التلقائي".
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>
، ويُسجّلهما. يعرض المثال الأول عنصرًا مخصّصًا أساسيًا يسجّل نفسه داخل عملية الاستيراد. يوضّح المثال الثاني كيفية تنفيذ عنصر مخصّص ينشئ Shadow DOM من <template>
، ثم يسجّل نفسه.
إنّ أفضل ما في تسجيل العناصر المخصّصة داخل عملية استيراد HTML هو أنّ المستورِد يُعلِن ببساطة عن العنصر الخاص بك على صفحته. لا حاجة إلى توصيل الأسلاك.
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>
في رأيي، يجعل سير العمل هذا وحده ميزة "استيراد HTML" طريقة مثالية لمشاركة مكوّنات الويب.
إدارة التبعيات والاستيرادات الفرعية
عمليات الاستيراد الفرعية
قد يكون من المفيد أن يتضمّن أحد عمليات الاستيراد عملية أخرى. على سبيل المثال، إذا أردت إعادة استخدام مكوّن آخر أو توسيع نطاقه، استخدِم عملية استيراد لتحميل العناصر الأخرى.
في ما يلي مثال حقيقي من Polymer. وهو مكوّن علامة تبويب جديد (<paper-tabs>
) يعيد استخدام تنسيق ومكوّن أداة اختيار. تتم إدارة التبعيات باستخدام عمليات استيراد HTML.
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 أكثر من مرّة في كل صفحة يؤدي إلى حدوث أخطاء. ألا سيؤدي ذلك إلى حدوث مشكلة كبيرة في Web Components عندما تستخدم عناصر متعددة المكتبة نفسها؟ لا، إذا استخدمنا عمليات استيراد HTML. ويمكن استخدامها لإدارة التبعيات.
من خلال تضمين المكتبات في عملية استيراد HTML، يمكنك إزالة تكرار الموارد تلقائيًا. يتم تحليل المستند مرة واحدة فقط. يتم تنفيذ النصوص البرمجية مرة واحدة فقط. على سبيل المثال، لنفترض أنّك حدّدت ملف استيراد، 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 في العديد من أشجار الاستيراد المختلفة، لا يُستخرج المستند ويعالجه المتصفّح إلا مرة واحدة. يُثبت فحص لوحة الشبكة ذلك:

اعتبارات الأداء
إنّ عمليات استيراد HTML رائعة تمامًا، ولكن كما هو الحال مع أي تكنولوجيا جديدة على الويب، يجب استخدامها بحكمة. لا تزال أفضل ممارسات تطوير الويب سارية. في ما يلي بعض النقاط التي يجب أخذها في الاعتبار.
تسلسل عمليات الاستيراد
من المهم دائمًا تقليل طلبات الشبكة. إذا كان لديك العديد من روابط المحتوى المراد استيراده على مستوى أعلى، ننصحك بدمجها في مورد واحد واستيراد هذا الملف.
Vulcanize هي أداة إنشاء npm من فريق Polymer تعمل على تسطيح مجموعة من عمليات استيراد HTML بشكل متكرر في ملف واحد. يمكنك اعتبارها خطوة إنشاء تسلسل لمكوّنات الويب.
تستفيد عمليات الاستيراد من ذاكرة التخزين المؤقت للمتصفّح.
ينسى الكثير من المستخدمين أنّه تم ضبط حِزمة الشبكات في المتصفّح بدقة على مرّ السنين. تستفيد عمليات الاستيراد (والاستيراد الفرعي) من هذا المنطق أيضًا. قد تحتوي عملية استيراد http://cdn.com/bootstrap.html
على موارد فرعية، ولكن سيتم تخزينها مؤقتًا.
لا يكون المحتوى مفيدًا إلا عند إضافته.
فكِّر في المحتوى على أنّه غير نشط إلى أن تطلب خدماته. لنفترض أنّ لديك ملف أسلوب عادي تم إنشاؤه ديناميكيًا:
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'styles.css';
لن يطلب المتصفّح ملف styles.css إلى أن تتم إضافة link
إلى ملف تعريف DOM:
document.head.appendChild(link); // browser requests styles.css
هناك مثال آخر على الترميز الذي يتم إنشاؤه ديناميكيًا:
var h2 = document.createElement('h2');
h2.textContent = 'Booyah!';
لا يكون h2
ذا معنى نسبي إلى أن تتم إضافته إلى DOM.
ينطبق المفهوم نفسه على مستند الاستيراد. ما لم يتم إلحاق محتواه بنموذج كائن المستند (DOM)، لن يتم تنفيذه. في الواقع، إنّ العنصر الوحيد الذي "ينفَّذ" في مستند الاستيراد مباشرةً هو <script>
. اطّلِع على النصوص البرمجية في عمليات الاستيراد.
تحسين التحميل غير المتزامن
عمليات الاستيراد تحظر العرض
عمليات الاستيراد تحظر عرض الصفحة الرئيسية. ويشبه ذلك ما يفعله <link rel="stylesheet">
. ويعود سبب حظر المتصفّح لعرض ملفات الأنماط في المقام الأول إلى الحدّ من حدوث أخطاء FOUC. تتصرف عمليات الاستيراد بالطريقة نفسها لأنّها يمكن أن تحتوي على أوراق أسلوب.
لكي تكون غير متزامنة تمامًا ولا تحظر المُحلِّل أو العرض، استخدِم السمة async
:
<link rel="import" href="/path/to/import_that_takes_5secs.html" async>
لا يكون async
هو الإعداد التلقائي لملفات HTML Imports لأنّه يتطلّب من المطوّرين
بذل المزيد من الجهد. يعني الوضع المتزامن التلقائي أنّه يتم تحميل عمليات استيراد HTML التي تحتوي على تعريفات عناصر مخصّصة بترتيبها وإجراء الترقية لها. في حال عدم التزام التطبيقات بجدول زمني معيّن، على المطوّرين إدارة هذه العملية وتحديد مواعيد الترقية بأنفسهم.
يمكنك أيضًا إنشاء عملية استيراد غير متزامنة بشكل ديناميكي:
var l = document.createElement('link');
l.rel = 'import';
l.href = 'elements.html';
l.setAttribute('async', '');
l.onload = function(e) { ... };
لا تحظر عمليات الاستيراد عملية التحليل.
لا تحظر عمليات الاستيراد تحليل الصفحة الرئيسية. تتم معالجة النصوص البرمجية داخل عمليات الاستيراد بالترتيب، ولكنها لا تحظر صفحة الاستيراد. وهذا يعني أنّك تحصل على سلوك مشابه لـ defer مع الحفاظ على ترتيب النص البرمجي الصحيح. من مزايا وضع بيانات الاستيراد في <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"
بوضع رمز التتبّع في <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>
ملاحظات يجب تذكرها
نوع محتوى الملف المستورَد هو
text/html
.يجب تفعيل بروتوكول CORS للموارد من مصادر أخرى.
يتم استرداد عمليات الاستيراد من عنوان URL نفسه وتحليلها مرة واحدة. وهذا يعني أنّه لا يتم تنفيذ النص البرمجي في عملية الاستيراد إلا في المرة الأولى التي يتم فيها عرض عملية الاستيراد.
تتم معالجة النصوص البرمجية في عملية الاستيراد بالترتيب، ولكنّها لا تحظر تحليل المستند الرئيسي.
لا يعني رابط الاستيراد "#include the content here". ويعني ذلك "أداة التحليل، انتقِل إلى جلب هذا المستند حتى أتمكّن من استخدامه لاحقًا". أثناء تنفيذ النصوص البرمجية في وقت الاستيراد، يجب إضافة ملفات الأنماط والترميز والموارد الأخرى إلى الصفحة الرئيسية بشكل صريح. ملاحظة: لا حاجة إلى إضافة
<style>
بشكل صريح. هذا هو الفرق الرئيسي بين عمليات استيراد HTML و<iframe>
، التي تشير إلى "تحميل هذا المحتوى وعرضه هنا".
الخاتمة
تسمح عمليات استيراد HTML بتجميع HTML/CSS/JS كمورد واحد. على الرغم من أنّ هذه الفكرة مفيدة بحد ذاتها، إلا أنّها تصبح فعّالة للغاية في عالم مكوّنات الويب. يمكن للمطوّرين إنشاء مكوّنات قابلة لإعادة الاستخدام ليستخدمها الآخرون ويدمجوها في تطبيقاتهم، وكل ذلك من خلال <link rel="import">
.
إنّ عمليات استيراد HTML هي مفهوم بسيط، ولكنها تتيح عددًا من حالات الاستخدام المثيرة للاهتمام للمنصّة.
حالات الاستخدام
- توزيع HTML/CSS/JS ذات الصلة كمجموعة واحدة من الناحية النظرية، يمكنك استيراد تطبيق ويب بالكامل إلى تطبيق آخر.
- تنظيم الرموز البرمجية: تقسيم المفاهيم منطقيًا إلى ملفات مختلفة، ما يشجع على استخدام الوحدات وإعادة الاستخدام**
- أرسِل تعريفًا واحدًا أو أكثر من تعريفات العنصر المخصّص. يمكن استخدام عملية الاستيراد register العناصر وتضمينها في تطبيق. ويساعد ذلك في تطبيق أنماط البرامج الجيدة، مع فصل واجهة/تعريف العنصر عن طريقة استخدامه.
- إدارة التبعيات: يتم تلقائيًا إزالة تكرار الموارد.
- تقسيم النصوص البرمجية: قبل عمليات الاستيراد، كان يتم تحليل ملف مكتبة JS الكبيرة بالكامل لبدء تشغيلها، ما كان يؤدي إلى بطء العملية. باستخدام عمليات الاستيراد، يمكن للمكتبة بدء العمل فور تحليل الجزء "أ". وقت استجابة أقل
// TODO: DevSite - Code sample removed as it used inline event handlers
تحليل HTML بشكل موازٍ: هي المرة الأولى التي يتم فيها تشغيل محلّلَي HTML (أو أكثر) بشكل موازٍ في المتصفّح.
يتيح التبديل بين وضع تصحيح الأخطاء ووضع عدم تصحيح الأخطاء في التطبيق، وذلك بمجرد تغيير هدف الاستيراد نفسه. لا يحتاج تطبيقك إلى معرفة ما إذا كان هدف الاستيراد هو مورد مجمّع/مجمّع أو شجرة استيراد.