What’s the purpose of the HTML “nomodule” attribute for script elements if the default is text/javascript?

dman picture dman · Aug 29, 2017 · Viewed 16.1k times · Source

I am not clearly understanding why the nomodule attribute exists in the new browsers that support ES6 modules.

In HTML 5, the type attribute is optional and defaults to text/javascript:

The type attribute gives the language of the script or format of the data. If the attribute is present, its value must be a valid MIME type. The charset parameter must not be specified. The default, which is used if the attribute is absent, is "text/javascript".

It doesn't default to <script type="module" src="module.js"></script>. Has this default changed? If not, why would nomodule be necessary? Can I just use <script src="bundle.js"></script> without nomodule?

Answer

sideshowbarker picture sideshowbarker · Aug 29, 2017

The purpose of the nomodule attribute is to cause newer browsers that support module scripts to ignore a particular script element:

The nomodule attribute is a boolean attribute that prevents a script from being executed in user agents that support module scripts.

The spec has a good example:

This example shows how to include a module script for modern user agents, and a classic script for older user agents:

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

In modern user agents that support module scripts, the script element with the nomodule attribute will be ignored, and the script element with a type of "module" will be fetched and evaluated (as a module script). Conversely, older user agents will ignore the script element with a type of "module", as that is an unknown script type for them — but they will have no problem fetching and evaluating the other script element (as a classic script), since they do not implement the nomodule attribute.

So that’s how it works.

In HTML 5, the type attribute is optional and defaults to text/javascript… Has this default changed?

The default hasn’t changed—it’s still text/javascript. But the type attribute can now also have the value module, which means browsers still parse and execute it as text/javascript—but also specifically as a module script.

If not, why would nomodule be necessary?

It’s necessary in order to prevent new browsers that support module scripts from executing a script that’s intended only for old browsers that don’t support module scripts, as in the above example.

Can I just use <script src="bundle.js"></script> without nomodule?

Yes—if bundle.js doesn’t use modules. If it uses modules, you‘d want to put type=module on it (in which case old browsers will ignore it since they don’t recognize the module value for type).