รวมสำหรับเว็บ
เหตุผลที่ควรนําเข้า
ลองนึกถึงวิธีที่คุณโหลดทรัพยากรประเภทต่างๆ บนเว็บ สำหรับ JS เรามี <script src>
สําหรับ CSS ตัวเลือกที่เหมาะสําหรับคุณน่าจะเป็น <link rel="stylesheet">
สำหรับรูปภาพจะเป็น <img>
วิดีโอมี <video>
เสียง <audio>
… เข้าประเด็นเลย เนื้อหาส่วนใหญ่ของเว็บมีวิธีโหลดตัวเองที่ง่ายและชัดเจน แต่ไม่ใช่สำหรับ HTML ตัวเลือกของคุณมีดังนี้
<iframe>
- ได้ผลดีแต่มีน้ำหนักมาก เนื้อหาของ iframe จะอยู่ในบริบทที่แยกจากหน้าเว็บของคุณโดยสิ้นเชิง แม้ว่าฟีเจอร์นี้จะยอดเยี่ยม แต่ก็ยังทำให้เกิดปัญหาเพิ่มเติม (การปรับขนาดเฟรมให้พอดีกับเนื้อหานั้นทำได้ยากมาก เขียนสคริปต์เข้า/ออกจากเฟรมได้ยากมาก และแทบจะจัดสไตล์ไม่ได้)- AJAX - ฉันชอบ
xhr.responseType="document"
แต่คุณบอกว่าฉันต้องใช้ JS เพื่อโหลด HTML ไม่น่าเป็นไปได้ - CrazyHacks™ - ฝังอยู่ในสตริง ซ่อนอยู่ในรูปแบบความคิดเห็น (เช่น
<script type="text/html">
) น่าขยะแขยง
เข้าใจความย้อนแย้งไหม เนื้อหาพื้นฐานที่สุดของเว็บอย่าง HTML ต้องใช้ความพยายามมากที่สุดในการดำเนินการ แต่โชคดีที่เรามีคอมโพเนนต์ของเว็บที่จะช่วยเรากลับมาทำงานได้ตามปกติ
เริ่มต้นใช้งาน
การนําเข้า HTML ซึ่งเป็นส่วนหนึ่งของการแคสต์ Web Components เป็นวิธีรวมเอกสาร 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 จะทำงานอย่างไร อย่างไรก็ตาม Polyfill ของ webcomponents.js จะใช้งานได้ดีในเบราว์เซอร์อื่นๆ จนกว่าจะมีการใช้งานอย่างแพร่หลาย
การรวมทรัพยากร
การนำเข้าเป็นระบบในการรวม 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 API มาตรฐาน
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 ของหน้าเว็บที่นําเข้าได้ ดังนี้
ตัวอย่าง - purchase.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
จึงหมายถึงเอกสารหน้าหลัก ผลที่ตามมาที่เป็นประโยชน์ 2 ประการ ได้แก่- ฟังก์ชันที่กําหนดในการนําเข้าจะปรากฏใน
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>
การลงทะเบียนองค์ประกอบที่กำหนดเอง
องค์ประกอบที่กำหนดเองเป็นเทคโนโลยี 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>
การนําเข้านี้จะกําหนด (และลงทะเบียน) องค์ประกอบ 2 รายการ ได้แก่ <say-hi>
และ <shadow-element>
รายการแรกแสดงองค์ประกอบที่กำหนดเองพื้นฐานที่ลงทะเบียนตัวเองภายในการนําเข้า ตัวอย่างที่ 2 แสดงวิธีใช้องค์ประกอบที่กําหนดเองซึ่งสร้าง 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 เป็นวิธีการที่เหมาะสมในการแชร์คอมโพเนนต์ของเว็บ
การจัดการทรัพยากร Dependency และการนําเข้าย่อย
การนําเข้าย่อย
ซึ่งอาจมีประโยชน์สำหรับการนําเข้ารายการหนึ่งเพื่อรวมรายการอื่น เช่น หากต้องการนําคอมโพเนนต์อื่นมาใช้ซ้ำหรือขยาย ให้ใช้การนําเข้าเพื่อโหลดองค์ประกอบอื่นๆ
ด้านล่างนี้เป็นตัวอย่างจริงจาก Polymer คอมโพเนนต์นี้เป็นคอมโพเนนต์แท็บใหม่ (<paper-tabs>
) ที่ใช้เลย์เอาต์และคอมโพเนนต์ตัวเลือกซ้ำ จัดการทรัพยากร Dependency โดยใช้การนําเข้า 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 มากกว่า 1 ครั้งต่อหน้าเว็บทำให้เกิดข้อผิดพลาด การดำเนินการนี้จะไม่ก่อให้เกิดปัญหาใหญ่สำหรับคอมโพเนนต์เว็บเมื่อคอมโพเนนต์หลายรายการใช้ไลบรารีเดียวกันใช่ไหม ก็จะไม่ถ้าเราใช้การนำเข้า 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 จะรวมอยู่ในต้นไม้การนําเข้าหลายรายการ แต่เบราว์เซอร์จะดึงข้อมูลและประมวลผลเอกสารเพียงครั้งเดียว การตรวจสอบแผงเครือข่ายยืนยันข้อมูลนี้
ข้อพิจารณาด้านประสิทธิภาพ
การนำเข้า 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 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>
สิ่งที่ต้องจดจำ
Mimetype ของการนําเข้าคือ
text/html
ทรัพยากรจากต้นทางอื่นๆ ต้องเปิดใช้ CORS
การนำเข้าจาก URL เดียวกันจะถูกดึงและแยกวิเคราะห์เพียงครั้งเดียว ซึ่งหมายความว่าสคริปต์ในการนำเข้าจะทำงานเฉพาะครั้งแรกที่เห็นการนำเข้าเท่านั้น
สคริปต์ในการนำเข้าจะได้รับการประมวลผลตามลำดับ แต่ไม่บล็อกการแยกวิเคราะห์เอกสารหลัก
ลิงก์การนําเข้าไม่ได้หมายถึง "#include the content here" ซึ่งหมายความว่า "ไปดึงข้อมูลเอกสารนี้มาเพื่อให้ฉันใช้ภายหลัง" ในขณะที่สคริปต์ทำงานในขณะนำเข้า จะต้องเพิ่มสไตล์ชีต มาร์กอัป และทรัพยากรอื่นๆ ลงในหน้าหลักอย่างชัดเจน โปรดทราบว่าคุณไม่จำเป็นต้องเพิ่ม
<style>
อย่างชัดเจน ความแตกต่างที่สำคัญระหว่างการนําเข้า HTML กับ<iframe>
คือ<iframe>
จะระบุว่า "โหลดและแสดงผลเนื้อหานี้ที่นี่"
บทสรุป
การนําเข้า HTML ช่วยให้คุณสามารถรวม HTML/CSS/JS เป็นทรัพยากรรายการเดียวได้ แม้ว่าจะมีประโยชน์ในตัวเอง แต่ความคิดนี้ก็กลายเป็นสิ่งที่ทรงพลังอย่างยิ่งในโลกของ Web Components นักพัฒนาแอปสามารถสร้างคอมโพเนนต์ที่ใช้ซ้ำได้เพื่อให้คนอื่นๆ ใช้งานและนำเข้ามาในแอปของตน โดยทั้งหมดจะนำส่งผ่าน <link rel="import">
การนําเข้า HTML เป็นแนวคิดที่เรียบง่าย แต่เปิดโอกาสให้แพลตฟอร์มมีกรณีการใช้งานที่น่าสนใจหลายกรณี
กรณีการใช้งาน
- เผยแพร่ HTML/CSS/JS ที่เกี่ยวข้องเป็นกลุ่มเดียว ตามหลักแล้ว คุณอาจนำเข้าเว็บแอปทั้งแอปไปยังเว็บแอปอื่นได้
- การจัดระเบียบโค้ด - จัดแบ่งแนวคิดออกเป็นไฟล์ต่างๆ อย่างมีเหตุผล ซึ่งจะช่วยส่งเสริมความเป็นโมดูลและความสามารถในการนํากลับมาใช้ใหม่**
- ส่งคําจํากัดความองค์ประกอบที่กําหนดเองอย่างน้อย 1 รายการ การนำเข้าสามารถใช้เพื่อregisterและรวมไว้ในแอป การดำเนินการนี้จะทำให้รูปแบบซอฟต์แวร์ที่ดี ทำให้อินเทอร์เฟซ/คำจำกัดความขององค์ประกอบแยกจากการใช้งาน
- จัดการทรัพยากรที่เกี่ยวข้อง - ระบบจะกรองทรัพยากรที่ซ้ำกันออกโดยอัตโนมัติ
- แยกสคริปต์เป็นกลุ่ม - ก่อนที่จะนําเข้า ไลบรารี JS ขนาดใหญ่จะต้องแยกวิเคราะห์ไฟล์ทั้งหมดเพื่อเริ่มทํางาน ซึ่งทําให้ช้า เมื่อนำเข้าแล้ว ไลบรารีจะเริ่มทํางานทันทีที่แยกวิเคราะห์ข้อมูลส่วน A เวลาในการตอบสนองน้อยลง
// TODO: DevSite - Code sample removed as it used inline event handlers
แยกวิเคราะห์ HTML แบบขนาน - เป็นครั้งแรกที่เบราว์เซอร์สามารถเรียกใช้โปรแกรมแยกวิเคราะห์ HTML 2 รายการ (หรือมากกว่า) พร้อมกัน
เปิดใช้การสลับระหว่างโหมดแก้ไขข้อบกพร่องและโหมดที่ไม่แก้ไขข้อบกพร่องในแอปได้ง่ายๆ เพียงเปลี่ยนเป้าหมายการนําเข้า แอปของคุณไม่จําเป็นต้องทราบว่าเป้าหมายการนําเข้าเป็นทรัพยากรที่รวม/คอมไพล์ หรือโครงสร้างการนำเข้า