عمليات استيراد HTML

تضمين المحتوى على الويب

لماذا الاستيراد؟

فكر في كيفية تحميل أنواع مختلفة من الموارد على الويب. بالنسبة إلى JavaScript، لدينا <script src>. بالنسبة إلى CSS، من المرجّح أن يكون <link rel="stylesheet"> هو الخيار المفضّل لديك. بالنسبة إلى الصور، تكون القيمة <img>. يتضمّن الفيديو <video>. الصوت، <audio>… ادخل في صلب الموضوع. إنّ معظم محتوى الويب يستخدم طريقة بسيطة وواضحة لتحميل نفسه. لا ينطبق ذلك على HTML. إليك الخيارات المتاحة لك:

  1. <iframe>: أسلوب مجرّب وفعّال، ولكنه ثقيل. يظهر محتوى إطار iframe بالكامل في سياق منفصل عن صفحتك. على الرغم من أنّ هذه الميزة رائعة في معظم الأحيان، إلا أنّها تطرح تحديات إضافية (من الصعب تصغير حجم الإطار ليناسب المحتوى، ومن الصعب جدًا إنشاء نص برمجي للإطار أو الخروج منه، ومن شبه المستحيل تطبيق تنسيق عليه).
  2. AJAX - أحبّ xhr.responseType="document"، ولكن هل أنت بحاجة إلى JavaScript لتحميل HTML؟ يبدو أنّ هناك مشكلة.
  3. 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> الخاصة بعملية الاستيراد إلى الصفحة الرئيسية. يتم تنفيذ النص البرمجي مرة أخرى.
  • لا تحظر عمليات الاستيراد تحليل الصفحة الرئيسية. ومع ذلك، تتم معالجة النصوص البرمجية داخلها بالترتيب. وهذا يعني أنّك تحصل على سلوك مشابه لسلوك التأخير مع الحفاظ على ترتيب النص البرمجي الصحيح. يمكنك الاطّلاع أدناه على مزيد من المعلومات حول هذا الموضوع.

عرض مكوّنات الويب

يُعدّ تصميم عمليات استيراد 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>

تسجيل العناصر المخصّصة

العناصر المخصصة هي تقنية أخرى لمكوّن الويب تعمل بشكل جيد للغاية مع عمليات استيراد 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" طريقة مثالية لمشاركة مكوّنات الويب.

إدارة التبعيات والاستيرادات الفرعية

عمليات الاستيراد الفرعية

قد يكون من المفيد أن يتضمّن أحد عمليات الاستيراد عملية أخرى. على سبيل المثال، إذا أردت إعادة استخدام مكوّن آخر أو توسيع نطاقه، استخدِم عملية استيراد لتحميل العناصر الأخرى.

في ما يلي مثال حقيقي من بوليمر. إنه مكوّن جديد لعلامة التبويب (<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 في العديد من أشجار الاستيراد المختلفة، لا يُستخرج المستند ويعالجه المتصفّح إلا مرة واحدة. يُثبت فحص لوحة الشبكة ما يلي:

يتم طلب jquery.html مرة واحدة
يتم طلب 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، لأنّه يتطلب من المطوّرين بذل جهد إضافي. يعني الوضع المتزامن التلقائي أنّه يتم تحميل عمليات استيراد HTML التي تحتوي على تعريفات عناصر مخصّصة بترتيبها وإجراء الترقية لها. في حال عدم التزام المطوّرين بجدول زمني محدّد، عليهم إدارة هذه العملية وتحديد مواعيد الترقية بأنفسهم.

يمكنك أيضًا إنشاء عملية استيراد غير متزامنة بشكل ديناميكي:

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" بوضع رمز التتبّع في <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 ذات الصلة كحزمة واحدة من الناحية النظرية، يمكنك استيراد تطبيق ويب بالكامل إلى تطبيق آخر.
  • تنظيم الرموز: يمكنك تقسيم المفاهيم بشكل منطقي إلى ملفات مختلفة، ما يشجع على استخدام وحدات نمطية وإمكانية إعادة الاستخدام**.
  • أرسِل تعريفًا واحدًا أو أكثر من تعريفات العناصر المخصّصة. يمكن استخدام عملية الاستيراد لتسجيل العناصر وتضمينها في تطبيق. ويساعد ذلك في تطبيق أنماط البرامج الجيدة، مع فصل واجهة/تعريف العنصر عن طريقة استخدامه.
  • إدارة التبعيات: يتم تلقائيًا إزالة تكرار الموارد.
  • النصوص البرمجية التقسيمية: قبل عمليات الاستيراد، يتم تحليل ملف مكتبة JS الكبيرة الحجم بالكامل لبدء تشغيلها، وكان ذلك بطيئًا. باستخدام عمليات الاستيراد، يمكن للمكتبة بدء العمل فور تحليل الجزء "أ". وقت استجابة أقل
// TODO: DevSite - Code sample removed as it used inline event handlers
  • تحليل HTML بشكل موازٍ: هي المرة الأولى التي يتم فيها تشغيل محلّلَي HTML (أو أكثر) بشكل موازٍ في المتصفّح.

  • يتيح التبديل بين وضع تصحيح الأخطاء ووضع عدم تصحيح الأخطاء في التطبيق، وذلك بمجرد تغيير هدف الاستيراد نفسه. لا يحتاج تطبيقك إلى معرفة ما إذا كان هدف الاستيراد هو مورد مجمّع/مجمّع أو شجرة استيراد.