Modules in the Browser and Node.js
ES modules use the same import and export syntax, but different environments have different loading rules.
The two environments you will hear about most are:
- browsers
- Node.js
Modern build tools also affect how modules work in real projects.
Browser Modules
In a browser, a JavaScript file can use imports if it is loaded as a module.
<script type="module" src="./app.js"></script>Then app.js can import other modules.
// app.js
import { add } from "./math.js";
console.log(add(2, 3));Without type="module", the browser treats the file as a normal script.
Then import statements will not work.
Browser Module Paths
Browser module imports usually need explicit paths.
import { add } from "./math.js";The ./ means the file is in the same folder.
This is different:
import { add } from "math.js";The browser does not treat this as a local relative file path.
For local files, use ./ or ../.
File Extensions
In browser modules, include the file extension.
import { add } from "./math.js";Some bundlers allow this:
import { add } from "./math";But plain browser modules usually need:
./math.jsModules Are Deferred by Default
Browser module scripts are deferred by default.
That means they wait for the HTML document to be parsed before running.
<script type="module" src="./app.js"></script>You usually do not need to add defer.
This makes modules safer than old scripts that could run before the page was ready.
Module Scope in Browsers
Top-level variables in modules do not become global variables.
// app.js
const message = "Hello";This does not create window.message.
That is a good thing.
Modules help prevent accidental global pollution.
Node.js Modules
Node.js supports two module systems:
- CommonJS
- ES modules
CommonJS uses:
const fs = require("fs");
module.exports = {};ES modules use:
import fs from "node:fs";
export {};This module focuses on ES modules.
Enabling ES Modules in Node.js
Common ways to use ES modules in Node:
Use .mjs files:
app.mjsOr set "type": "module" in package.json:
{
"type": "module"
}Then .js files are treated as ES modules.
Node Built-In Imports
Node.js has built-in modules.
Modern code often uses the node: prefix.
import { readFile } from "node:fs/promises";
const text = await readFile("./data.txt", "utf8");The node: prefix makes it clear that the import is a Node built-in module.
Package Imports
In projects with dependencies, you may import packages.
import express from "express";This does not start with ./ because it is not a local file.
It comes from node_modules.
Browsers do not understand package imports directly without tooling.
Bundlers or runtimes resolve them.
Bundlers and Dev Tools
Modern frontend projects commonly use tools such as Vite.
They let you write imports like:
import { createApp } from "vue";
import "./styles.css";
import logoUrl from "./logo.svg";Plain browsers do not handle all of those import types by themselves.
The tool processes them for you.
Best Practices
Use explicit relative paths for local files:
import { add } from "./math.js";Use type="module" for browser module scripts.
Know whether your project uses plain browser modules, Node.js, or a bundler.
Do not mix CommonJS and ES module syntax randomly.
Follow your project's module style.
Common Mistakes
Mistake 1: Forgetting type="module"
<script src="./app.js"></script>If app.js uses imports:
<script type="module" src="./app.js"></script>Mistake 2: Missing ./ for Local Files
import { add } from "math.js";Correct:
import { add } from "./math.js";Mistake 3: Assuming Browser and Bundler Rules Are Identical
A bundler may allow imports that a browser does not understand directly.
Always know what environment is running your code.
Summary
ES modules work in browsers, Node.js, and bundler-based projects, but loading rules differ.
- Browser modules use
<script type="module">. - Browser local imports usually need
./,../, and file extensions. - Module scripts are deferred by default.
- Node.js supports both CommonJS and ES modules.
- Node can use ES modules with
.mjsor"type": "module". - Bundlers can support extra import features beyond plain browsers.