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

הדפדפן לא יבקש את 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 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 גדולה היה עובר ניתוח מלא כדי להתחיל לפעול, והתהליך היה איטי. באמצעות ייבוא, הספרייה יכולה להתחיל לפעול ברגע שניתוח הקטע A מסתיים. זמן אחזור קצר יותר!
// TODO: DevSite - Code sample removed as it used inline event handlers
  • ניתוח HTML במקביל – בפעם הראשונה הדפדפן יכול להריץ שני מנתח HTML (או יותר) במקביל.

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