ES Modules in Browsers (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.
type="module"
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:
- All module scripts run in deferred mode - meaning they load and execute only after the HTML document is fully loaded.
- Module scripts have their own scope, and
thisinside them isundefined, notwindow. - You can use
importandexportin module files.
The defer attribute and module scripts
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.
The nomodule attribute
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:
- If the browser supports
type="module", it will loadmodern.js. - If the browser doesn't support
type="module", it will loadlegacy.js.
Important: nomodule only works in non-module browsers. Modern browsers completely ignore scripts with nomodule.
Example: Using Module System in Browsers
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.
Conclusion
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.