
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.

TanStack Start and Router: What You Need to Know
An overview of TanStack Start and TanStack Router — type-safe routing, validated search params, server functions, middleware, SSR, and how to get started.
Aurora Scharff
Apr 9, 2026

Handling Content in Nuxt
A practical walkthrough of @nuxt/content for querying, rendering, and navigating markdown-based content in Nuxt.
Reza Baar
Apr 8, 2026

How to Pick the Right Dependencies for Your Angular Application
Choosing the right libraries/dependencies for your Angular applications can make or break your project in the long run. Learn how to pick the right dependencies.
Alain Chautard
Apr 7, 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.
