This is standardized now and supported by all major modern browsers.
will the modules be loaded asynchronously?
Yes, with two options available; details below.
Referencing only my main or entry file and browsers will lazy load the requiere modules.
Not so much "lazy," but yes.
Enabling it
Details in the spec here and here (and possibly elsewhere).
To get this behavior, you specify that your script is a module by using type="module"
:
<script src="main.js" type="module"></script>
or for inline scripts
<script type="module">
// ...module code here
</script>
That means that the script is parsed and handled per the Module definition in the JavaScript specification instead of per the Script definition, which means it can have imports (and exports).
Imports are resolved relative to the script's URL (for modules loaded via a separate resource such as the main.js
above, just like CSS) or relative to the document (for inline modules like the one above).
So for instance, if I have this in my document at http://example.com/index.html
:
<script src="./handy/stuff/nifty.js" type="module"></script>
...and nifty.js
contains
import Thingy from "./thingy.js";
...then the browser looks for http://example.com/handy/stuff/thingy.js
, not http://example.com/thingy.js
. Again, just like CSS imports.
Note that the ./
on that module specifier is required, just from "thingy.js"
won't work. That's because bare specifiers are disallowed because they'll probably end up having a special meaning. (For instance, in Node.js, that's how you specify built-in modules, and modules installed in node_modules
.) A module specifier must be a full URL, or a relative URL starting with /
, ./
, or ../
.
Async
I said above that modules are loaded asynchronously, and there are two options available. This graphic from the spec says it best (see the spec for the latest copy of it):
As you can see, for type="module"
scripts, if you don't put any special flag attributes on the script
tag, all of the module's dependencies will be resolved and then the script will be run once parsing of the HTML is complete. If you include the async
attribute, it may run sooner, before the HTML parsing is complete (for instance, if all the scripts are in cache). (defer
is not valid for modules.)