ES Modules in the browser
ES Modules in the browser (type="module", defer, nomodule)
When ES Modules were first introduced to JavaScript, they also gained native browser support. This allowed us to use import
and export
in browsers without any bundlers (like Webpack). In this article, we'll see how ES Modules work in browsers and the roles of type="module"
, defer
, and nomodule
attributes.
A regular <script>
tag executes immediately in the browser, but if you want to use import
/export
statements, you need to add type="module"
to the script tag:
<script type="module" src="main.js"></script>
Key points:
this
inside them is undefined
, not window
.import
and export
in module files.In regular <script>
tags, using defer
means the script should load in the background and execute only after the HTML is fully loaded.
But with module scripts, type="module"
already works like defer
by default. So you don't need to explicitly add the defer
attribute - it's already applied.
<script type="module" src="main.js"></script>
This script will automatically wait until the HTML is fully loaded before executing.
To provide a fallback JavaScript file for older browsers (that don't support ES Modules), we can use the nomodule
attribute.
<script type="module" src="modern.js"></script>
<script nomodule src="legacy.js"></script>
What happens here:
type="module"
, it will load modern.js
.type="module"
, it will load legacy.js
.Important: nomodule
only works in non-module browsers. Modern browsers completely ignore scripts with nomodule
.
Let's look at a simple example of how to export and import a function between files in the browser.
// greet.js
export function greet(name) {
console.log(`Hello, ${name}!`);
}
// main.js
import { greet } from './greet.js';
greet('Ani');
<!-- index.html -->
<script type="module" src="main.js"></script>
When the browser loads main.js
, it will find greet.js
and execute the functions in the correct order.
ES Modules in browsers allow us to create more organized, modular, and modern web applications. Remember to use type="module"
for module scripts and nomodule
for supporting older browsers. This has become a fundamental standard in frontend development today.