Nhập HTML

Thêm cho web

Tại sao cần nhập?

Hãy nghĩ về cách bạn tải các loại tài nguyên khác nhau trên web. Đối với JS, chúng ta có <script src>. Đối với CSS, bạn có thể sử dụng <link rel="stylesheet">. Đối với hình ảnh, đó là <img>. Video có <video>. Âm thanh, <audio>… Vào thẳng trọng tâm! Phần lớn nội dung trên web có cách tự tải đơn giản và mang tính khai báo. Nhưng không phải như vậy đối với HTML. Bạn có thể chọn một trong những cách sau:

  1. <iframe> – đã thử và đúng nhưng nặng. Nội dung của iframe nằm hoàn toàn trong một ngữ cảnh riêng biệt với trang của bạn. Mặc dù đây chủ yếu là một tính năng tuyệt vời, nhưng nó cũng tạo ra thêm nhiều thách thức (rất khó để thu nhỏ kích thước khung cho nội dung, cực kỳ khó khăn khi viết tập lệnh vào/ra, gần như không thể tạo kiểu).
  2. AJAXTôi thích xhr.responseType="document", nhưng bạn đang nói rằng tôi cần JS để tải HTML? Có vẻ như không chính xác.
  3. CrazyHacks™ – được nhúng trong các chuỗi, ẩn dưới dạng nhận xét (ví dụ: <script type="text/html">). Thật kinh tởm!

Bạn thấy sự trớ trêu không? Nội dung cơ bản nhất của web, HTML, đòi hỏi nhiều nỗ lực nhất để xử lý. Rất may, Thành phần web sẽ giúp chúng ta quay lại đúng hướng.

Bắt đầu

HTML Imports (Tệp nhập HTML), một phần của nhóm truyền Web Components (Thành phần web), là một cách để đưa tài liệu HTML vào các tài liệu HTML khác. Bạn cũng không bị giới hạn ở việc sử dụng mã đánh dấu. Một lệnh nhập cũng có thể bao gồm CSS, JavaScript hoặc bất kỳ nội dung nào khác mà tệp .html có thể chứa. Nói cách khác, tính năng này giúp hoạt động nhập trở thành công cụ tuyệt vời để tải HTML/CSS/JS có liên quan.

Khái niệm cơ bản

Thêm một tệp nhập trên trang bằng cách khai báo <link rel="import">:

<head>
    <link rel="import" href="/path/to/imports/stuff.html">
</head>

URL của một tệp nhập được gọi là vị trí nhập. Để tải nội dung từ một miền khác, vị trí nhập cần bật CORS:

<!-- Resources on other origins must be CORS-enabled. -->
<link rel="import" href="http://example.com/elements.html">

Phát hiện và hỗ trợ tính năng

Để phát hiện khả năng hỗ trợ, hãy kiểm tra xem .import có tồn tại trên phần tử <link> hay không:

function supportsImports() {
    return 'import' in document.createElement('link');
}

if (supportsImports()) {
    // Good to go!
} else {
    // Use other libraries/require systems to load files.
}

Tính năng hỗ trợ trình duyệt vẫn đang trong giai đoạn đầu. Chrome 31 là trình duyệt đầu tiên triển khai nhưng các nhà cung cấp trình duyệt khác đang chờ xem Mô-đun ES sẽ hoạt động như thế nào. Tuy nhiên, đối với các trình duyệt khác, webcomponents.js polyfill hoạt động rất tốt cho đến khi mọi thứ được hỗ trợ rộng rãi.

Gói tài nguyên

Các lệnh nhập cung cấp quy ước để đóng gói HTML/CSS/JS (thậm chí cả các lệnh nhập HTML khác) thành một sản phẩm phân phối duy nhất. Đây là một tính năng nội tại nhưng rất mạnh mẽ. Nếu bạn đang tạo giao diện, thư viện hoặc chỉ muốn phân đoạn ứng dụng thành các phần hợp lý, thì việc cung cấp cho người dùng một URL duy nhất là điều cần thiết. Thậm chí, bạn có thể phân phối toàn bộ ứng dụng thông qua một tệp nhập. Hãy suy nghĩ về điều đó trong giây lát.

Một ví dụ thực tế là Bootstrap. Bootstrap bao gồm các tệp riêng lẻ (bootstrap.css, bootstrap.js, phông chữ), yêu cầu JQuery cho các trình bổ trợ và cung cấp các ví dụ về mã đánh dấu. Nhà phát triển thích tính linh hoạt của lựa chọn theo yêu cầu. Điều này cho phép họ sử dụng những phần của khung mà họ muốn sử dụng. Tuy nhiên, tôi cá rằng JoeDeveloper™ thông thường sẽ chọn cách dễ dàng và tải tất cả Bootstrap xuống.

Việc nhập sẽ rất hữu ích cho các công cụ như Bootstrap. Tôi xin giới thiệu với bạn về tương lai của việc tải Bootstrap:

<head>
    <link rel="import" href="bootstrap.html">
</head>

Người dùng chỉ cần tải một đường liên kết Nhập HTML. Họ không cần phải lo lắng về việc phân tán các tệp. Thay vào đó, toàn bộ Bootstrap được quản lý và gói gọn trong một tệp nhập, 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>

Hãy để yên. Đây là những nội dung thú vị.

Sự kiện tải/lỗi

Phần tử <link> sẽ kích hoạt sự kiện load khi một lượt nhập được tải thành công và onerror khi lượt nhập không thành công (ví dụ: nếu tài nguyên 404).

Các lệnh nhập sẽ cố gắng tải ngay lập tức. Một cách dễ dàng để tránh đau đầu là sử dụng các thuộc tính 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)">

Hoặc nếu bạn đang tạo tệp nhập một cách linh động:

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);

Sử dụng nội dung

Việc đưa một lệnh nhập vào một trang không có nghĩa là "đưa nội dung của tệp đó vào đây". Tức là "trình phân tích cú pháp, hãy tìm nạp tài liệu này để tôi có thể sử dụng". Để thực sự sử dụng nội dung, bạn phải hành động và viết tập lệnh.

Một khoảnh khắc aha! quan trọng là nhận ra rằng một lệnh nhập chỉ là một tài liệu. Trên thực tế, nội dung của một tệp nhập được gọi là tài liệu nhập. Bạn có thể thao tác với nội dung nhập bằng các API DOM chuẩn!

link.import

Để truy cập vào nội dung của một tệp nhập, hãy sử dụng thuộc tính .import của phần tử đường liên kết:

var content = document.querySelector('link[rel="import"]').import;

link.importnull trong các điều kiện sau:

  • Trình duyệt không hỗ trợ tính năng Nhập HTML.
  • <link> không có rel="import".
  • <link> chưa được thêm vào DOM.
  • <link> đã bị xoá khỏi DOM.
  • Tài nguyên không bật CORS.

Ví dụ đầy đủ

Giả sử warnings.html chứa:

<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>

Trình nhập có thể lấy một phần cụ thể của tài liệu này và sao chép phần đó vào trang của họ:

<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>

Tập lệnh trong các lệnh nhập

Nội dung nhập không có trong tài liệu chính. Các lớp này là vệ tinh của lớp đó. Tuy nhiên, hoạt động nhập vẫn có thể diễn ra trên trang chính ngay cả khi tài liệu chính là tài liệu tối cao. Một tệp nhập có thể truy cập vào DOM của chính tệp đó và/hoặc DOM của trang đang nhập tệp đó:

Ví dụ – import.html thêm một trong các tệp kiểu vào trang chính

<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>

Hãy chú ý đến những gì đang diễn ra ở đây. Tập lệnh bên trong lệnh nhập tham chiếu đến tài liệu đã nhập (document.currentScript.ownerDocument) và thêm một phần của tài liệu đó vào trang nhập (mainDoc.head.appendChild(...)). Khá phức tạp nếu bạn hỏi tôi.

Quy tắc của JavaScript trong một tệp nhập:

  • Tập lệnh trong quá trình nhập được thực thi trong ngữ cảnh của cửa sổ chứa document đang nhập. Vì vậy, window.document đề cập đến tài liệu trang chính. Điều này có hai hệ quả hữu ích:
    • các hàm được xác định trong một lệnh nhập sẽ kết thúc trên window.
    • bạn không cần phải làm gì khó khăn như thêm các khối <script> của lệnh nhập vào trang chính. Một lần nữa, tập lệnh sẽ được thực thi.
  • Các lệnh nhập không chặn việc phân tích cú pháp trang chính. Tuy nhiên, các tập lệnh bên trong chúng được xử lý theo thứ tự. Điều này có nghĩa là bạn sẽ nhận được hành vi giống như trì hoãn trong khi vẫn duy trì thứ tự tập lệnh thích hợp. Hãy xem thêm thông tin về vấn đề này ở bên dưới.

Phân phối thành phần web

Thiết kế của tính năng Nhập HTML rất phù hợp để tải nội dung có thể sử dụng lại trên web. Cụ thể, đây là cách lý tưởng để phân phối Thành phần web. Mọi thứ từ <template> HTML cơ bản đến Phần tử tuỳ chỉnh đầy đủ với Shadow DOM [1, 2, 3]. Khi các công nghệ này được sử dụng song song, các lệnh nhập sẽ trở thành #include cho Thành phần web.

Bao gồm mẫu

Phần tử Mẫu HTML rất phù hợp với tính năng Nhập HTML. <template> rất phù hợp để tạo các phần đánh dấu cho ứng dụng nhập để sử dụng theo ý muốn. Việc gói nội dung trong <template> cũng mang lại cho bạn lợi ích bổ sung là làm cho nội dung không hoạt động cho đến khi được sử dụng. Tức là các tập lệnh sẽ không chạy cho đến khi mẫu được thêm vào DOM). Xong rồi!

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>

Đăng ký phần tử tuỳ chỉnh

Thành phần tuỳ chỉnh là một công nghệ Thành phần web khác hoạt động rất hiệu quả với tính năng Nhập HTML. Các lệnh nhập có thể thực thi tập lệnh, vậy tại sao bạn không xác định + đăng ký các phần tử tuỳ chỉnh để người dùng không phải làm điều đó? Hãy gọi đó là…"tự động đăng ký".

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>

Lệnh nhập này xác định (và đăng ký) hai phần tử là <say-hi><shadow-element>. Mục đầu tiên hiển thị một phần tử tuỳ chỉnh cơ bản tự đăng ký bên trong phần nhập. Ví dụ thứ hai cho thấy cách triển khai một phần tử tuỳ chỉnh tạo Shadow DOM từ <template>, sau đó tự đăng ký.

Điều tuyệt vời nhất khi đăng ký các phần tử tuỳ chỉnh bên trong tệp nhập HTML là trình nhập chỉ cần khai báo phần tử của bạn trên trang của họ. Không cần đi dây.

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>

Theo tôi, quy trình làm việc này đã khiến tính năng Nhập HTML trở thành một cách lý tưởng để chia sẻ Thành phần web.

Quản lý phần phụ thuộc và lệnh nhập phụ

Lệnh nhập phụ

Một lệnh nhập có thể hữu ích khi bao gồm một lệnh nhập khác. Ví dụ: nếu bạn muốn sử dụng lại hoặc mở rộng một thành phần khác, hãy sử dụng lệnh nhập để tải(các) phần tử khác.

Dưới đây là ví dụ thực tế từ Polymer. Đây là một thành phần thẻ mới (<paper-tabs>) sử dụng lại bố cục và thành phần bộ chọn. Các phần phụ thuộc được quản lý bằng tính năng Nhập HTML.

paper-tabs.html (đơn giản):

<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>

Nhà phát triển ứng dụng có thể nhập phần tử mới này bằng cách sử dụng:

<link rel="import" href="paper-tabs.html">
<paper-tabs></paper-tabs>

Trong tương lai, khi có một <iron-selector2> mới, tuyệt vời hơn, bạn có thể hoán đổi <iron-selector> và bắt đầu sử dụng ngay. Bạn sẽ không làm người dùng gặp sự cố nhờ các thành phần nhập và web.

Quản lý phần phụ thuộc

Chúng ta đều biết rằng việc tải JQuery nhiều lần trên mỗi trang sẽ gây ra lỗi. Điều này có phải là vấn đề lớn đối với Thành phần web khi nhiều thành phần sử dụng cùng một thư viện không? Không nếu chúng ta sử dụng hàm Nhập HTML! Bạn có thể dùng các tệp này để quản lý các phần phụ thuộc.

Bằng cách gói các thư viện trong một tệp nhập HTML, bạn sẽ tự động loại bỏ các tài nguyên trùng lặp. Tài liệu chỉ được phân tích cú pháp một lần. Tập lệnh chỉ được thực thi một lần. Ví dụ: giả sử bạn xác định một tệp nhập, jquery.html, để tải một bản sao của JQuery.

jquery.html

<script src="http://cdn.com/jquery.js"></script>

Bạn có thể sử dụng lại lệnh nhập này trong các lệnh nhập tiếp theo như sau:

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>

Ngay cả trang chính cũng có thể bao gồm jquery.html nếu cần thư viện:

<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>

Mặc dù jquery.html có trong nhiều cây nhập khác nhau, nhưng tài liệu của tệp này chỉ được trình duyệt tìm nạp và xử lý một lần. Việc kiểm tra bảng điều khiển mạng đã chứng minh điều này:

jquery.html được yêu cầu một lần
jquery.html được yêu cầu một lần

Xem xét hiệu suất

Tính năng Nhập HTML là một tính năng tuyệt vời, nhưng giống như mọi công nghệ web mới, bạn nên sử dụng tính năng này một cách khôn ngoan. Các phương pháp hay nhất về phát triển web vẫn đúng. Dưới đây là một số điều cần lưu ý.

Nhập nối

Việc giảm số lượng yêu cầu mạng luôn quan trọng. Nếu bạn có nhiều đường liên kết nhập cấp cao nhất, hãy cân nhắc kết hợp các đường liên kết đó thành một tài nguyên duy nhất và nhập tệp đó!

Vulcanize là một công cụ xây dựng npm của nhóm Polymer. Công cụ này lồng nhau làm phẳng một tập hợp các lệnh Nhập HTML thành một tệp duy nhất. Hãy xem đây là bước tạo chuỗi kết hợp cho Thành phần web.

Tính năng nhập tận dụng tính năng lưu vào bộ nhớ đệm của trình duyệt

Nhiều người quên rằng ngăn xếp mạng của trình duyệt đã được điều chỉnh tinh vi trong nhiều năm. Các lệnh nhập (và lệnh nhập phụ) cũng tận dụng logic này. Tệp nhập http://cdn.com/bootstrap.html có thể có tài nguyên phụ, nhưng các tài nguyên này sẽ được lưu vào bộ nhớ đệm.

Nội dung chỉ hữu ích khi bạn thêm nội dung

Hãy xem nội dung là không hoạt động cho đến khi bạn gọi các dịch vụ của nội dung đó. Lấy một tệp định kiểu thông thường, được tạo động:

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

Trình duyệt sẽ không yêu cầu styles.css cho đến khi link được thêm vào DOM:

document.head.appendChild(link); // browser requests styles.css

Một ví dụ khác là mã đánh dấu được tạo động:

var h2 = document.createElement('h2');
h2.textContent = 'Booyah!';

h2 tương đối vô nghĩa cho đến khi bạn thêm nó vào DOM.

Khái niệm tương tự cũng áp dụng cho tài liệu nhập. Trừ phi bạn thêm nội dung của tệp này vào DOM, nếu không thì tệp này sẽ không hoạt động. Trên thực tế, <script> là thành phần duy nhất "thực thi" trực tiếp trong tài liệu nhập. Xem phần viết tập lệnh trong các lệnh nhập.

Tối ưu hoá để tải không đồng bộ

Nhập chặn quá trình kết xuất

Các tệp nhập chặn quá trình hiển thị trang chính. Điều này tương tự như những gì <link rel="stylesheet"> làm. Lý do trình duyệt chặn việc kết xuất trên các tệp định kiểu ngay từ đầu là để giảm thiểu FOUC. Các tệp nhập hoạt động tương tự vì có thể chứa các trang định kiểu.

Để hoàn toàn không đồng bộ và không chặn trình phân tích cú pháp hoặc kết xuất, hãy sử dụng thuộc tính async:

<link rel="import" href="/path/to/import_that_takes_5secs.html" async>

Lý do async không phải là mặc định cho tính năng Nhập HTML là vì tính năng này yêu cầu nhà phát triển phải làm nhiều việc hơn. Đồng bộ theo mặc định có nghĩa là các tệp nhập HTML có định nghĩa phần tử tuỳ chỉnh bên trong sẽ được đảm bảo tải và nâng cấp theo thứ tự. Trong một thế giới hoàn toàn không đồng bộ, nhà phát triển sẽ phải tự quản lý và nâng cấp thời gian.

Bạn cũng có thể tạo một hoạt động nhập không đồng bộ một cách linh động:

var l = document.createElement('link');
l.rel = 'import';
l.href = 'elements.html';
l.setAttribute('async', '');
l.onload = function(e) { ... };

Các lệnh nhập không chặn quá trình phân tích cú pháp

Thao tác nhập không chặn việc phân tích cú pháp trang chính. Các tập lệnh bên trong lệnh nhập được xử lý theo thứ tự nhưng không chặn trang nhập. Điều này có nghĩa là bạn sẽ nhận được hành vi giống như trì hoãn trong khi vẫn duy trì thứ tự tập lệnh thích hợp. Một lợi ích của việc đặt các lệnh nhập vào <head> là cho phép trình phân tích cú pháp bắt đầu xử lý nội dung sớm nhất có thể. Tuy nhiên, điều quan trọng là bạn phải nhớ <script> trong tài liệu chính vẫn tiếp tục chặn trang. <script> đầu tiên sau khi nhập sẽ chặn quá trình hiển thị trang. Đó là do một lệnh nhập có thể có tập lệnh bên trong cần được thực thi trước tập lệnh trong trang chính.

<head>
    <link rel="import" href="/path/to/import_that_takes_5secs.html">
    <script>console.log('I block page rendering');</script>
</head>

Tuỳ thuộc vào cấu trúc ứng dụng và trường hợp sử dụng, có một số cách để tối ưu hoá hành vi không đồng bộ. Các kỹ thuật dưới đây giúp giảm thiểu việc chặn quá trình kết xuất trang chính.

Tình huống 1 (ưu tiên): bạn không có tập lệnh trong <head> hoặc nội tuyến trong <body>

Bạn nên đặt <script> sau khi nhập dữ liệu. Di chuyển tập lệnh càng trễ trong trò chơi càng tốt…nhưng bạn đã thực hiện phương pháp hay nhất đó, PHẢI KHÔNG!? ;)

Ví dụ:

<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>

Mọi thứ đều ở dưới cùng.

Tình huống 1.5: lệnh nhập tự thêm vào

Một cách khác là yêu cầu tính năng nhập thêm nội dung của riêng nó. Nếu tác giả nhập thiết lập một hợp đồng để nhà phát triển ứng dụng tuân theo, thì nội dung nhập có thể tự thêm vào một khu vực trên trang chính:

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>

Tình huống #2: bạn tập lệnh trong <head> hoặc nội tuyến trong <body>

Nếu một tệp nhập mất nhiều thời gian để tải, thì <script> đầu tiên theo sau tệp đó trên trang sẽ chặn việc hiển thị trang. Ví dụ: Google Analytics recommend đặt mã theo dõi trong <head>. Nếu bạn không thể tránh việc đặt <script> trong <head>, thì việc thêm mã nhập một cách linh động sẽ ngăn chặn việc chặn trang:

<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>

Ngoài ra, bạn có thể thêm lệnh nhập vào gần cuối <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>

Những điều cần nhớ

  • Loại MIME của tệp nhập là text/html.

  • Các tài nguyên từ các nguồn gốc khác cần được bật CORS.

  • Các tệp nhập từ cùng một URL sẽ được truy xuất và phân tích cú pháp một lần. Điều đó có nghĩa là tập lệnh trong một lệnh nhập chỉ được thực thi trong lần đầu tiên thấy lệnh nhập đó.

  • Các tập lệnh trong một lệnh nhập được xử lý theo thứ tự, nhưng không chặn quá trình phân tích cú pháp tài liệu chính.

  • Đường liên kết nhập không có nghĩa là "#include the content here" ("#bao gồm nội dung tại đây"). Tức là "trình phân tích cú pháp, hãy tìm nạp tài liệu này để tôi có thể sử dụng sau". Mặc dù các tập lệnh thực thi tại thời điểm nhập, nhưng bạn cần thêm rõ ràng các tệp kiểu, mã đánh dấu và tài nguyên khác vào trang chính. Lưu ý: Bạn không cần thêm <style> một cách rõ ràng. Đây là điểm khác biệt chính giữa HTML Imports và <iframe>, trong đó "load and render this content here" (tải và hiển thị nội dung này tại đây) có nghĩa là "tải và hiển thị nội dung này tại đây".

Kết luận

Tính năng Nhập HTML cho phép đóng gói HTML/CSS/JS dưới dạng một tài nguyên duy nhất. Mặc dù bản thân ý tưởng này rất hữu ích, nhưng nó trở nên cực kỳ mạnh mẽ trong thế giới Thành phần web. Nhà phát triển có thể tạo các thành phần có thể sử dụng lại để người khác sử dụng và đưa vào ứng dụng của riêng họ, tất cả đều được phân phối thông qua <link rel="import">.

Nhập HTML là một khái niệm đơn giản, nhưng cho phép một số trường hợp sử dụng thú vị cho nền tảng.

Trường hợp sử dụng

  • Phân phối HTML/CSS/JS liên quan dưới dạng một gói duy nhất. Về lý thuyết, bạn có thể nhập toàn bộ ứng dụng web vào một ứng dụng web khác.
  • Sắp xếp mã – phân đoạn các khái niệm một cách hợp lý thành nhiều tệp, khuyến khích tính mô-đun và khả năng sử dụng lại**.
  • Phân phối một hoặc nhiều định nghĩa Phần tử tuỳ chỉnh. Bạn có thể dùng lệnh nhập để register và đưa các phần tử đó vào ứng dụng. Phương pháp này áp dụng các mẫu phần mềm tốt, tách biệt giao diện/định nghĩa của phần tử với cách sử dụng phần tử đó.
  • Quản lý phần phụ thuộc – tài nguyên được tự động loại bỏ trùng lặp.
  • Gói tập lệnh – trước khi nhập, thư viện JS có kích thước lớn sẽ phân tích cú pháp toàn bộ tệp để bắt đầu chạy, điều này sẽ làm chậm quá trình. Với các lệnh nhập, thư viện có thể bắt đầu hoạt động ngay khi phân tích cú pháp đoạn A. Độ trễ thấp hơn!
// TODO: DevSite - Code sample removed as it used inline event handlers
  • Tiến hành phân tích cú pháp HTML song song – lần đầu tiên trình duyệt có thể chạy song song hai (hoặc nhiều) trình phân tích cú pháp HTML.

  • Cho phép chuyển đổi giữa chế độ gỡ lỗi và chế độ không gỡ lỗi trong một ứng dụng, chỉ bằng cách thay đổi chính mục tiêu nhập. Ứng dụng của bạn không cần biết liệu mục tiêu nhập là tài nguyên được đóng gói/biên dịch hay cây nhập.