16
votes

TLDR: On what specific grounds did browser-makers reject, deprecate and remove HTML Imports?


This is me (four hours ago):

Apparently I have been living under a rock, because only today I have discovered a web-shaking innovation which sounds tremendously exciting:

HTML Imports - #Include for the Web (Nov 2013)

Crikey. November 2013? That's more than half a decade ago!

HTML IMPORTS?! Really?! Really really?!!

This is something I've wanted to see since the early 2000s!

Wow, look at this: <link rel="import" href="/document-to-import.html">

This looks... amazing. Let's see if there are any other articles about this unheard-of innovation...

:: Pulls out no fewer than 39 articles from search engine discussing HTML Imports. ::

Wow... there's so much to read. (39 pages! No kidding!!) Everyone seems to know all about this stuff. Half the world appears to have written about what an exciting new innovation this is. (Innovation from 2013, anyway...)


:: Pauses for thought after reading several pages in breathless wonder ::

Although... how come I've never heard of HTML Imports ??

Doesn't Firefox... ? Let me just...

:: Runs to check Can I Use HTML Imports ::

Ahhhhhh. I see. Never implemented in Firefox. (Or in Safari).


And what's this I'm now reading everywhere about HTML Imports being deprecated?

HTML Imports deprecated from Chrome 73 onwards and due to be removed in Chrome 80 (Jan 2020)? Whaaaat?! Noooo!! No - I've only just discovered this!!

And the feature is right here on Can I Use HTML Imports. On Chrome and Opera. And - look! - it's just started on Edge, too!!

See?! Not deprecated! Even Edge will now be supporting HTML Imports! It surely can't be deprecated? More and more browsers are supporting it!


Oh. Hang on. Doesn't Opera use WebKit instead of Presto now?

:: Checks ::

Ah. Right. Opera uses the Blink Browser Engine. Same as Chrome. So Opera supports HTML Imports only because Blink does.

Hmm.

What's that?

:: Checks again ::

Oh. Edge 79 is based on Chromium 79. So Edge also uses the Blink Browser Engine now. Same as Chrome. So Edge supports HTML Imports only because Blink does.

So, basically no browser engine supports HTML Imports. Except Blink.

And even Blink deprecated HTML Imports in Chromium 73.

  • WebKit doesn't support.
  • Presto never supported.
  • EdgeHTML never supported.
  • Gecko doesn't support.

And now Blink has removed HTML Imports.


Well, that was a rollercoaster.

6 years' worth of fun in 2 hours.

After reading all that, my impression is that Mozilla, particularly, was never keen on:

<link rel="import" href="/document-to-import.html">

I can't see any response from Safari, but I don't see any explicit enthusiasm from that corner, either.

Yet, after scouring the web, I still can't find the reasons articulated anywhere for opposing, rejecting, deprecating and removing HTML Imports.

Question:

On what specific grounds did browser-makers reject, deprecate and remove HTML Imports?

  • 2
    It's my understanding that it was only ever experimental, was then deprecated and is now obsolete.. mainly due to vendors. Interesting read on it here: hacks.mozilla.org/2015/06/the-state-of-web-components – Bronwyn V Jan 30 at 0:31
  • Thank you, @BronwynV - that was an informative reference. I've done some more hunting around and I've seen that as long ago as 2016-17, HTML Modules were proposed as a potential successor to HTML Imports here: Webcomponents Issues and here: HTML-Imports-and-ES-Modules. – Rounin Jan 30 at 1:47
  • Further: HTML Modules are still being discussed in 2019, here: HTML Modules, here: Intent to Implement: HTML Modules, here: HTML Modules Design Document and here: HTML Modules Explainer. – Rounin Jan 30 at 1:57
  • 1
    Just adding a keyword for future internet searches - transclusion. – Anssssss Jan 30 at 19:49
  • 2
    I agree that an SE question should include all relevant information in the question body. The reason I did not explain the term HTML Imports is because I thought the term self-explanatory: a technology which enables web documents to import HTML. If that's not immediately obvious, I am happy to add an explanatory note to the question above. – Rounin Jan 31 at 18:42
18
votes

After reading several articles on this, the general consensus is that HTML Imports were redundant, since you need JavaScript to bring them alive anyways (they don't just automatically add themselves into the document - the term "include" is kind of misleading if you compare it to what that usually means in other languages).

From the article that @Bronwyn linked:

As previously stated, Mozilla is not currently intending to implementing HTML Imports. This is in part because we’d like to see how ES6 modules pan out before shipping another way of importing external assets, and partly because we don’t feel they enable much that isn’t already possible.

We’ve been working with Web Components in Firefox OS for over a year and have found using existing module syntax (AMD or Common JS) to resolve a dependency tree, registering elements, loaded using a normal tag seems to be enough to get stuff done.

The state of Web Components - Mozilla Hacks

So in short, they didn't really enable you to do anything that you can't do with existing JS modules.

2
votes

Nota Bene:

HTML Imports are deprecated as a standalone technology, but it turns out the underlying concept has not been ditched.


It appears (after much searching) that HTML Imports (deprecated) may yet be succeeded by HTML Modules.

Here are two very readable documents from the W3C introducing HTML Modules:

  1. HTML Modules Proposal - W3C
  2. HTML Modules Explainer - W3C

The first document details the specific problems thrown up by HTML Imports and reveals how HTML Modules will solve these problems.

Specific problems with HTML Imports include:

  • Parsing Obstruction: Any <script> referenced after a <link rel="import"> declaration must wait for the imported HTML to fully download, obstructing the parsing and delaying the download of the rest of the main document

  • Global Namespace Conflicts: Any JS variable declared within the HTML Import will clash with an identically-named JS variable declared in the main document

The second document discusses in more detail how HTML Modules will work in practice.


More info on HTML Modules proposals:


In Conclusion:

It wasn't so much that the concept behind HTML Imports was no good.

It was simply that the implementation architecture - initially developed in 2011, a long time before ES6 Modules were finalised - has proven far from optimal, especially given the evolution, more recently, of more sophisticated technologies.

0
votes

On what specific grounds did browser-makers reject, deprecate and remove HTML Imports?

Good question. But it turns out concerns about the removal of HTML Imports might be largely irrelevant.

How so?

We can recognise that there is no official spec for importing HTML into HTML at present, since:

  • The official spec for HTML Imports has been rejected, deprecated and removed
  • HTML Modules - which may, at some point, replace HTML Imports - are still a work-in-progress

But that matters less than it initially appears to, because an unofficial and largely undocumented approach to importing HTML will never be deprecated or removed. (Arguably can never be deprecated or removed.)

"HTML Imports are dead. Long live html imports!"

What?!

It turns out (who knew?) that - even without an official spec - it absolutely is possible to import HTML into the current HTML document, using contemporary, standard technologies (HTML + JS).

The following technique doesn't have an official name (nor, at present, very much recognition), but since it uses the following three standard, long established technologies:

  • <object> / <iframe> HTML5 Elements
  • .contentDocument property
  • before() / insertBefore() methods

it's going to remain a robust technique until HTML Modules are good to go.


Importing HTML using <object> or <iframe> as a helper

This 4-step technique was brilliantly documented by Scott Jehl in:

It works identically (and equally well) using either of two HTML5 elements (<object> or <iframe>) as an intermediate helper.

1) We can display one html file inside another via either of these elements:

<object data="/my-html-import.html"></object>

<iframe src="/my-html-import.html"></iframe>

2) When the helper element (either <object> or <iframe>) is loaded, we can reach inside it, extract the contentDocument and add that to the parent document, just before the element, using:

this.before(this.contentDocument.body.children[0]);

3) Then, the helper element can be removed from the document using:

this.remove();

4) As an additional touch, the helper element can be styled such that it never visibly renders in the viewport in the first place, using:

display: none;

Putting this all together (with styles and scripts as inline attributes), gives us:

<object data="/my-html-import.html" style="display: none;" onload="this.before(this.contentDocument.body.children[0]); this.remove();"></object>

<iframe src="/my-html-import.html" style="display: none;" onload="this.before(this.contentDocument.body.children[0]); this.remove();"></iframe>

Once either helper element has completed running the javascript in its onload attribute, the external html will have been successfully imported into the current HTML document and there will no longer be any trace of the element.

Result: HTML imported.


Additional Note:

The walkthrough above constructs helper elements with an inline style attribute and an inline event listener attribute. But if we need to separate structure from presentation from behaviour, we can straightforwardly convert the self-contained element(s) above into a setup implementing unobtrusive CSS and Javascript:

HTML:

<object class="html-import-helper" data="/my-html-import.html"></object>

or

<iframe class="html-import-helper" src="/my-html-import.html"></iframe>

CSS:

.html-import-helper {
  display: none;
}

Javascript:

const htmlImportHelper = document.getElementsByClassName('html-import-helper')[0];

const importHTML = (e) => {
  e.target.before(e.target.contentDocument.body.children[0]);
  e.target.remove();
}

htmlImportHelper.addEventListener('load', importHTML);

Not the answer you're looking for? Browse other questions tagged or ask your own question.