ייבוא HTML

הוספת קישור עומק לאינטרנט

למה צריך ייבוא?

כדאי לחשוב על האופן שבו אתם מעלים סוגים שונים של משאבים לאינטרנט. ב-JS, יש לנו את <script src>. כשמדובר ב-CSS, סביר להניח שהיעד שלך הוא <link rel="stylesheet">. לתמונות, השדה הזה הוא <img>. הסרטון כולל <video>. אודיו, <audio>… התמקדו בנושא! לרוב התוכן באינטרנט יש דרך פשוטה ודקלרטיבית לטעון את עצמו. לא כך לגבי HTML. אלה האפשרויות שעומדות לרשותכם:

  1. <iframe> – ניסית ואמיתי, אבל כבדה. התוכן של iframe נמצא בהקשר נפרד לחלוטין מהדף שלכם. זו תכונה נהדרת בדרך כלל, אבל היא יוצרת אתגרים נוספים (כיווץ גודל המסגרת לתוכן שלו הוא קשה, ומתסכל מאוד לכתוב את הסקריפט לתוך או מחוצה לו, כמעט בלתי אפשרי לתכנת).
  2. AJAXאני אוהב את xhr.responseType="document", אבל האם אתם אומרים שאני צריך JS כדי לטעון HTML? נראה שזה לא נכון.
  3. CrazyHacks™ – מוטמעות במחרוזות, מוסתרות כתגובות (למשל <script type="text/html">). איכס!

רואים מה האירוניה? התוכן הבסיסי ביותר של האינטרנט, HTML, דורש את המאמץ הרב ביותר כדי לעבוד איתו. למרבה המזל, רכיבי אינטרנט עוזרים לנו לחזור למסלול.

תחילת העבודה

ייבוא קובצי HTML, חלק מהטיפוס רכיבי אינטרנט, הוא דרך לכלול מסמכי HTML במסמכי HTML אחרים. אתם גם לא מוגבלים לסימני Markup. ייבוא יכול לכלול גם 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 Modules יתפתחו. עם זאת, בדפדפנים אחרים, ה-polyfill של webcomponents.js פועל מצוין עד שהדברים יהיו נתמכים באופן נרחב.

קיבוץ משאבים

ייבוא מספק מוסכמה לשילוב של HTML/CSS/JS (כולל פעולות ייבוא אחרות של HTML) בחומרה אחת. זוהי תכונה מהותית, אבל עוצמתית. אם אתם יוצרים נושא, ספרייה או שאתם פשוט רוצים לפלח את האפליקציה לחלקים הגיוניים, כדאי לתת למשתמשים כתובת URL אחת. אפשר אפילו לייבא אפליקציה שלמה. כדאי לחשוב על זה רגע.

דוגמה מהעולם האמיתי היא Bootstrap. Bootstrap מורכב מקובצים נפרדים (bootstrap.css,‏ bootstrap.js,‏ fonts), מחייב את JQuery עבור הפלאגינים שלו ומספק דוגמאות לתגי markup. מפתחים אוהבים את הגמישות שניתנת לבחירה. היא מאפשרת להם לקנות את החלקים של המסגרת שבהם הם רוצים להשתמש. ולמרות זאת, אני מתערב ש-JoeDeveloperTM הטיפוסי שלך עובר במסלול הקל, ומוריד את כל ה-Butstrap.

ייבוא הגיוני מאוד למשהו כמו אתחול אתחול. הנה העתיד של טעינת 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! למעשה, התוכן של ייבוא נקרא מסמך ייבוא. אתם יכולים לבצע שינויים בנתוני הייבוא באמצעות ממשקי API רגילים של 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' מתאים לטעינת תוכן לשימוש חוזר באינטרנט. במיוחד, זו דרך אידיאלית להפצת רכיבי Web. כל דבר, החל מרכיבי HTML <template> בסיסיים ועד לרכיבים מותאמים אישית מלאים עם Shadow DOM [1, 2, 3]. כשמשתמשים בטכנולוגיות האלה במקביל, הייבוא הופך ל-#include לרכיבי אינטרנט.

כולל תבניות

אלמנט התבנית ב-HTML מתאים באופן טבעי לייבוא קובצי HTML. <template> נהדר ליצירת תבניות של קטעי רכיבי Markup, כדי שהאפליקציה המייבאת תוכל להשתמש בהם כרצונה. כשעוטפים תוכן ב-<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>

רישום רכיבים מותאמים אישית

רכיבים מותאמים אישית הם טכנולוגיה נוספת של Web Components שמתאימה בצורה מושלמת ל-HTML Imports. אפשר להריץ סקריפט באמצעות ייבוא, אז למה לא להגדיר ולרשום את הרכיבים המותאמים אישית כדי שהמשתמשים לא יצטרכו לעשות זאת? אפשר לקרוא לזה…'רישום אוטומטי'.

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>. בקוד הראשון מוצג רכיב מותאם אישית בסיסי שמירשם בעצמו בתוך הייבוא. הדוגמה השנייה מראה איך להטמיע רכיב מותאם אישית שיוצר 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 יותר מפעם אחת בכל דף גורמת לשגיאות. האם זו לא תהיה בעיה עצומה ברכיבי אינטרנט כשמספר רכיבים ישתמשו באותה ספרייה? לא אם משתמשים בייבוא קובצי 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 הוא כלי build של npm מצוות Polymer שמשטח באופן רקורסיבי קבוצה של ייבוא HTML לקובץ יחיד. אפשר לחשוב על זה כשלב עיבוד נתונים (build) של שרשור (concatenation) לרכיבי אינטרנט.

ייבוא שמשתמש בשמירה במטמון הדפדפן

אנשים רבים שוכחים שסטאק הרשתות של הדפדפן עבר שיפורים רבים לאורך השנים. גם תהליכי ייבוא (וייבוא משנה) מנצלים את הלוגיקה הזו. יכול להיות שייבוא http://cdn.com/bootstrap.html יכלול משאבי משנה, אבל הם יישמרו במטמון.

התוכן שימושי רק כשאתם מוסיפים אותו

התוכן נחשב כעצמאי עד שאתם קוראים לשירותים שלו. ניקח גיליון סגנונות רגיל שנוצר באופן דינמי:

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

הדפדפן לא ישלח בקשה ל-סגנונות.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> היא להימנע מיד לאחר הייבוא. כדאי להעביר את הסקריפטים לשלב מאוחר ככל האפשר במשחק... אבל כבר ביצעת את השיטה המומלצת הזו, AREN'T YOU!? ;)

לדוגמה:

<head>
    <link rel="import" href="/path/to/import.html">
    <link rel="import" href="/path/to/import2.html">
    <!-- avoid including script -->
</head>
<body>
    <!-- avoid including script -->

    <div id="container"></div>

    <!-- avoid including script -->
    ...

    <script>
    // Other scripts n' stuff.

    // Bring in the import content.
    var link = document.querySelector('link[rel="import"]');
    var post = link.import.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
    </script>
</body>

הכול נמצא בתחתית המסך.

תרחיש 1.5: הייבוא מוסיף את עצמו

אפשרות אחרת היא להוסיף תוכן משלכם באמצעות הייבוא. אם מחבר הייבוא יוצר חוזה שמפתח האפליקציה צריך לפעול לפיו, הייבוא יכול להוסיף את עצמו לאזור בדף הראשי:

import.html:

<div id="blog-post">...</div>
<script>
    var me = document.currentScript.ownerDocument;
    var post = me.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
</script>
index.html

<head>
    <link rel="import" href="/path/to/import.html">
</head>
<body>
    <!-- no need for script. the import takes care of things -->
</body>

תרחיש 2: יש לכם סקריפט ב-<head> או מוטמע ב-<body>

אם יש ייבוא שנדרש לו זמן רב לטעינה, ה-<script> הראשון שמופיע אחריו בדף יחסום את העיבוד של הדף. לדוגמה, ב-Google Analytics מומלץ להוסיף את קוד המעקב ל-<head>. אם אי אפשר להימנע מהוספת <script> ל-<head>, הוספה דינמית של הייבוא תמנע את החסימה של הדף:

<head>
    <script>
    function addImportLink(url) {
        var link = document.createElement('link');
        link.rel = 'import';
        link.href = url;
        link.onload = function(e) {
        var post = this.import.querySelector('#blog-post');

        var container = document.querySelector('#container');
        container.appendChild(post.cloneNode(true));
        };
        document.head.appendChild(link);
    }

    addImportLink('/path/to/import.html'); // Import is added early :)
    </script>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...
</body>

לחלופין, אפשר להוסיף את הייבוא לקראת סוף ה-<body>:

<head>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...

    <script>
    function addImportLink(url) { ... }

    addImportLink('/path/to/import.html'); // Import is added very late :(
    </script>
</body>

כדאי לזכור

  • ה-MIME type של ייבוא הוא 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 (או יותר) במקביל.

  • מאפשרת לעבור בין מצב ניפוי באגים למצב ללא ניפוי באגים באפליקציה, פשוט על ידי שינוי יעד הייבוא עצמו. האפליקציה לא צריכה לדעת אם יעד הייבוא הוא משאב חבילה/קובץ הידור או עץ ייבוא.