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

التضمين للويب

ما أهمية عمليات الاستيراد؟

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

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

تم null link.import وفقًا للشروط التالية:

  • لا يدعم المتصفّح عمليات استيراد ملفات 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 أكثر من مرة في كل صفحة يتسبب في حدوث أخطاء. ألن تكون هذه مشكلة كبيرة لمكونات الويب عندما تستخدم مكونات متعددة نفس المكتبة؟ ليس ذلك إذا كنا نستخدم عمليات استيراد 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';

لن يطلب المتصفِّح style.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>

أمور يجب تذكرها

  • نوع MIME لعملية الاستيراد هو text/html.

  • يجب تفعيل الموارد من المصادر الأخرى باستخدام سياسة مشاركة الموارد المنتظمة (CORS).

  • ويتم استرداد عمليات الاستيراد من عنوان URL نفسه وتحليلها مرة واحدة. وهذا يعني أنّه لا يتم تنفيذ النص البرمجي في عملية الاستيراد إلّا في المرة الأولى التي تتمّ فيها الاطّلاع على عملية الاستيراد.

  • تتم معالجة النصوص البرمجية في عملية الاستيراد بالترتيب، ولكن بدون حظر تحليل المستند الرئيسي.

  • لا يعني رابط الاستيراد "#include the content here". يعني ذلك "محلل لغوي، أريد استرجاع هذا المستند لأتمكّن من استخدامه لاحقًا". في حين يتم تنفيذ النصوص البرمجية في وقت الاستيراد، يجب إضافة أوراق الأنماط والترميز والموارد الأخرى إلى الصفحة الرئيسية بشكل صريح. تجدر الإشارة إلى أنّه لا حاجة إلى إضافة "<style>" بشكل صريح. وهذا يمثّل اختلافًا كبيرًا بين عمليات استيراد HTML و<iframe>، الذي ينص على "تحميل هذا المحتوى وعرضه هنا".

الخلاصة

تتيح عمليات استيراد HTML تجميع HTML/CSS/JS كمورد واحد. ورغم أن هذه الفكرة مفيدة في حد ذاتها، إلا أن هذه الفكرة تصبح قوية للغاية في عالم مكونات الويب. يمكن للمطوّرين إنشاء مكوّنات قابلة لإعادة الاستخدام ليتمكّن الآخرون من استخدامها وجلبها إلى تطبيقاتهم الخاصة، ويتم تقديم كل ذلك من خلال <link rel="import">.

تُعدّ عمليات استيراد HTML مفهومًا بسيطًا، إلا أنّه يتيح عددًا من حالات الاستخدام المثيرة للاهتمام بالنسبة إلى النظام الأساسي.

حالات الاستخدام

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

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