Translation of the article "HTML Imports #include for the web", Eric Bidelman.
From translator
I recently translated
an article on the basics of HTML Import . I promised that if this topic is of interest to the habr-community, I will translate a more detailed article. I decided to split the translation into two parts of equal size, since, in my opinion, there are too many beeches for one part. The second part will be released a few days after the publication of this part. If, of course, this part is more or less like the habr-community.
What is HTML import for?
Let's talk about how we load various resources. JavaScript we load with
<script src>
. For CSS we have
<link rel="stylesheet">
. For images
<img>
. For video there is
<video>
. For audio -
<audio>
... Let's get closer to the point! For most types of content there are simple ways to download it. But not for HTML. For HTML, we have the following options:
<iframe>
- tried and working, but ponderous way. Iframe content lives in a separate context from the main page. Although this is a good feature, it also creates additional difficulties: fitting the size of the i-frame to its content, working with internal scripts and styles.- AJAX - I like it
xhr.responseType="document"
, but loading HTML with JS does not look right. - TMT-curves - html code in the form of JS lines or comments, for example
<script type="text/html">
.
HTML code is the simplest type of content, but in this regard, it requires the greatest effort. It is good that we have
Web Components , they will help us deal with this and other problems.
Beginning of work
The
Web Components standard set contains the
HTML Imports standard, which allows HTML documents to be connected to each other. Linked HTML documents allow Javascript and CSS, in a word, all that .html usually contains. This is a great tool for downloading HTML / CSS / JS code packages.
')
The basics
The connection of documents takes place with the help of
<link rel="import">
:
<head> <link rel="import" href="/path/to/imports/stuff.html"> </head>
The specified URL
is the import location . To use import from another domain, its location must allow cross-domain resource sharing (CORS):
<link rel="import" href="http://example.com/elements.html">
Note: browsers ignore repeated requests for the same URL. This means that from one address only one download will be made, no matter how many connections are on the page.Check for browser support
To determine if the import is supported, check if the property exists.
import
in the elements
<link>
:
function supportsImports() { return 'import' in document.createElement('link'); } if (supportsImports()) {
Browser support is still at an early stage (approx. Translator: the original article was published on November 11, 2013, now, probably, the situation is different with support). Chrome 31 is the first browser that supports HTML import. Chrome 36 updated to the latest specification of this feature. You can enable import support by ticking the
“Enable experimental web platform features” checkbox at
about:flags
in chrome canary. For other browsers this does not work yet.
Note: The inclusion of experimental features will allow the use of other useful features of web components.Resource banding
HTML import allows you to build packages of HTML / CSS / JS code, which in turn can use other packages. This simple but powerful functionality can come in handy if you want to import a single resource to provide other programmers with some kind of library or set of styles. It is also useful for supporting the modularity of your application. You can even give away whole applications for import. Just think what can be achieved in this way.
You can export entire web content packages with just one link.
Bootstrap is a good example of how importing components might be useful. Bootstrap consists of various files (bootstrap.css, bootstrap.js, etc.), uses jQuery (as an imported component), and as a result produces tools for layout. Developers love the ability to plug in some modules as needed. But usually we go a simple way, connecting all the bootstrap modules at once.
An import would be very useful when using packages like Bootstrap. Here is what the connection might look like in the future:
<head> <link rel="import" href="bootstrap.html"> </head>
Just add one import link. You no longer need to connect a bunch of files; instead, the entire Bootstrap is wrapped in the bootstrap.html file:
<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> ... <template> ... </template>
Events load / error
After import loading
<link>
triggers an event
load
, and in case of an error (for example, 404), an event
error
.
Import always loads immediately, in order of finding the tag
<link>
. You can catch download events using attributes
onload/onerror
:
<script async> 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)">
Note: Load / error event handlers must be declared before import, as the browser loads the import at the moment it encounters the import tag. If there is no load handler at the time of import, the error undefined function will be displayed in the console.You can also dynamically create an import:
var link = document.createElement('link'); link.rel = 'import'; link.href = 'file.html' link.onload = function(e) {...}; link.onerror = function(e) {...}; document.head.appendChild(link);
Use Import Content
The import element on the page does not tell the browser where to place the contents of the import. It only tells the browser to get the document for further use. To use the contents of the import, we need to write a little JS code.
Here it is the moment of insight, import, it is just a document. In fact, the import content is called an
import document . And you can use the result of the import using standard DOM API tools!
link.import
To get the contents of the import, use the
.import
element property
.import
link
:
var content = document.querySelector('link[rel="import"]').import;
link.import
is
null
in the following circumstances:
- The browser does not support import.
- The item has
rel="import"
.
The object is DOM.
Or was removed from DOM
Resource does not support CORS.
Full example
Suppose we have a warnings.html
page:
<div class="warning"> <style scoped> h3 { color: red; } </style> <h3>Warning!</h3> <p>This page is under construction</p> </div> <div class="outdated"> <h3>Heads up!</h3> <p>This content may be out of date</p> </div>
You can use only the part of the imported page that you need:
<head> <link rel="import" href="warnings.html"> </head> <body> ... <script> var link = document.querySelector('link[rel="import"]'); var content = link.import; </script> </body>
Import scripts
The import doesn't quite work, as part of the document that uses it. But you can still work with the page that connected it. From the imported page, you can work with both the internal DOM and the main document:
Example - import.html adds one of its styles to the main document.
<link rel="stylesheet" href="http://www.example.com/styles.css"> <link rel="stylesheet" href="http://www.example.com/styles2.css"> <style> #somecontainer { color: blue; } </style> ... <script> </script>
So what is going on here? With help document.currentScript.ownerDocument
we access the internal root element of the imported document and add its piece to the main document ( mainDoc.head.appendChild(...)
). This is of course useless code, but we need it to understand that we can refer to both the main and the internal root of the DOM.
Scripts inside the import can both execute the code and provide functions for execution in the main document. This is similar to modules in Python .
Import rules:
- The import code is executed in the context of the document containing it. Two convenient things come from this:
- The functions declared in the import are contained in the main
window
object. - You do not need to do actions like adding tags to the main document.
<script>
from import. So the scripts inside the import are executed automatically.
- Import does not interrupt the loading of the main page code. At the same time, the scripts are executed in order. That is, deferred execution of scripts occurs. Further on this in more detail.