
A deep, practical explanation of JavaScript ES Modules: execution model, shared exports, strict mode, browser rules, and real-world implications.
Martin Ferret
March 3, 2026
For years, JavaScript grew without a native module system. Early applications were small, scripts lived in the global scope, and naming conflicts were common. As applications became larger and more complex, this approach quickly reached its limits.
Today, JavaScript modules (ES Modules) are everywhere: in browsers, Node.js, and every modern framework and bundler. Yet many developers use them daily without fully understanding how they actually work.
This article breaks down JavaScript modules from first principles, focusing on what is true, what matters, and why it works this way.
A JavaScript module is simply a file.
Each file is an isolated unit with:
Modules communicate only through:
export → what a module exposesimport → what a module consumes// sayHi.js export function sayHi(name) { return Hello ${name}; }
// main.js import { sayHi } from './sayHi.js';
console.log(sayHi('John'));
No implicit globals. No hidden dependencies. Everything is explicit.

Before native modules:
Modules solved these problems by enforcing:
This is not syntactic sugar: it is a structural foundation for large applications.
Modules automatically run in strict mode.
x = 10; // ❌ ReferenceError
This prevents silent errors and enforces safer code by default.
Top-level variables are never global.
// user.js export const user = 'John';
// app.js import { user } from './user.js'; console.log(user);
Without export and import, nothing is shared.
Even multiple <script type="module"> tags on the same page do not share scope.
No matter how many times a module is imported, its top-level code runs only once.
// logger.js console.log('Module initialized');
import './logger.js'; import './logger.js';
Output:
Module initialized
This behavior is intentional and fundamental.
Exports are live bindings, not snapshots.
// config.js export const config = {};
// init.js import { config } from './config.js'; config.user = 'Pete';
// feature.js import { config } from './config.js'; console.log(config.user); // Pete
All importers receive the same reference.
This enables controlled configuration and shared state, when used deliberately.
type="module" Is RequiredBrowsers only recognize modules when explicitly declared.
<script type="module" src="main.js"></script>
Without it, import and export will fail.
Module scripts:
This makes them behave similarly to defer, but by default.
This is invalid in the browser:
import { tool } from 'myLib'; // ❌
A path is required:
import { tool } from './myLib.js'; // ✅
Bare imports are resolved by:
Browsers do not resolve them natively.
ES modules do not work over file://.
You must use:
This is a security requirement, not a limitation.
import.meta: Module ContextEach module has access to metadata about itself:
console.log(import.meta.url);
Useful for:
Even with native modules, bundlers remain essential in production.
They provide:
In real-world applications, native modules are the input, bundlers are the output.
Modules enforce architectural clarity:
If a codebase feels messy with modules,
the issue is not the module system, it’s the architecture.
JavaScript modules are not an optional modern feature.
They are the foundation of contemporary JavaScript.
Understanding:
is what separates developers who use modules
from developers who control them.
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

JavaScript Modules Explained: The Foundation of Modern JS Applications
A deep, practical explanation of JavaScript ES Modules: execution model, shared exports, strict mode, browser rules, and real-world implications.
Martin Ferret
Mar 3, 2026

Server-side rendering: SSR or SSG, what’s the difference?
This is a clear breakdown of SSR (Server-Side Rendering) vs SSG (Static Site Generation) in Angular—explaining how they work, key differences like runtime vs build-time rendering, hydration behavior, server requirements, and how to choose the right strategy per route.
Alain Chautard
Feb 26, 2026

React Docs Refresh: useActionState and useOptimistic
The React docs for useActionState and useOptimistic have been rewritten with clearer naming, new interactive sandboxes, and patterns from simple pending states to shopping carts with error recovery. Here's what changed and why it matters.
Aurora Scharff
Feb 24, 2026
We can help you recruit Certified Developers for your organization or project. The team has helped many customers employ suitable resources from a pool of 100s of qualified Developers.
Let us help you get the resources you need.
