Skip to content

<nomodule>, or other patterns for loading both classic and module scripts? #1442

Description

@domenic

At BlinkOn @paulirish and a Facebook dev (Paul, do you have his GitHub handle?) were asking about how to ship down both classic scripts for old browsers and module scripts for new browsers. The idea is to ship pure ES6 code with a module graph for new browsers, and a transpiled bundle of code for older ones.

One idea here is to introduce <nomodule> element (analogous to <noscript>). Then you would write:

<script type="module" src="app.js"></script>
<nomodule>
  <script defer src="bundle.js"></script>
</nomodule>

Alternately a more targeted fix would be a nomodule attribute on <script>:

<script type="module" src="app.js"></script>
<script nomodule defer src="bundle.js"></script>

An alternative involving no new elements or attributes is to use JS-based feature detection, e.g.

<script type="module">
import "app.js";

window.__browserHasModules = true; // SyntaxError will occur otherwise
</script>
<script>
if (!window.__browserHasModules) {
  var s = document.createElement("script");
  s.src = "bundle.js";
  s.defer = true;
  document.head.appendChild(s);
}
</script>

However this will defeat the preload scanner (in the older browser case). You could try to work around it with <link rel="preload"> but then you'd fetch bundle.js even in newer browsers which is sad.

(EDIT: also, the above won't work because module scripts execute at "defer time"; we also would need to defer the evaluation of the above script, perhaps by listening to DOMContentLoaded.)

A third alternative is user-agent sniffing, of course.

Thoughts? Alternate ideas or patterns?

(Note: at first I thought <noscript type="module"> would work but it clearly would not because an old browser which does not support modules would just see it as a normal <noscript> and not execute the script-loading code inside.)

/cc @whatwg/modules

Metadata

Metadata

Assignees

No one assigned

    Labels

    addition/proposalNew features or enhancementsneeds implementer interestMoving the issue forward requires implementers to express interest

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions