import / export Syntax
Modules use export and import.
export makes code available outside the current file.
import brings exported code into another file.
Named Exports
A named export exports a value by name.
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}Another file can import those names:
// app.js
import { add, subtract } from "./math.js";
console.log(add(5, 2)); // 7
console.log(subtract(5, 2)); // 3The imported names must match the exported names.
Exporting After Declaration
You can define values first and export them later.
// math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
export { add, subtract };This is useful when you want exports grouped at the bottom of a file.
Exporting Variables
You can export constants and variables.
// config.js
export const apiUrl = "https://api.example.com";
export const timeout = 5000;Import them:
import { apiUrl, timeout } from "./config.js";Exporting Objects
// settings.js
export const settings = {
theme: "dark",
notifications: true,
};Import:
import { settings } from "./settings.js";
console.log(settings.theme); // darkImport Aliases
You can rename an import with as.
// user.js
export function format(name) {
return name.trim();
}// app.js
import { format as formatUserName } from "./user.js";
console.log(formatUserName(" Alice "));Aliases are useful when names conflict or need more context.
Export Aliases
You can also rename while exporting.
function formatName(name) {
return name.trim();
}
export { formatName as format };Another file imports the exported name:
import { format } from "./formatters.js";Namespace Imports
A namespace import collects all named exports into one object.
// math.js
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}// app.js
import * as math from "./math.js";
console.log(math.add(2, 3)); // 5
console.log(math.multiply(2, 3)); // 6This can be useful for utility modules.
Avoid overusing it when named imports would be clearer.
Import Paths
Local imports usually start with:
./..//in some environments
Example:
import { add } from "./math.js";./ means:
Start from the current file's folder.../ means:
Go up one folder.Example:
import { formatDate } from "../utils/date.js";In browser ES modules, file extensions are usually required:
import { add } from "./math.js";Bundlers may allow:
import { add } from "./math";But learning with explicit paths is clearer.
Imports Are Static
Normal import statements must be at the top level of a module.
import { add } from "./math.js";Do not put static imports inside if blocks or functions.
if (condition) {
import { add } from "./math.js"; // invalid static import
}For conditional loading, use dynamic import().
You will learn that later in this module.
Imports Are Read-Only Bindings
Imported bindings cannot be reassigned by the importing module.
import { apiUrl } from "./config.js";
apiUrl = "new-url"; // TypeErrorIf you need different configuration, export a function or create a new local value.
Live Bindings
ES module imports are live bindings.
That means if the exporting module changes an exported variable, importers see the updated value.
// counter.js
export let count = 0;
export function increment() {
count += 1;
}// app.js
import { count, increment } from "./counter.js";
console.log(count); // 0
increment();
console.log(count); // 1You cannot reassign count from app.js, but you can observe changes made by the exporting module.
Side-Effect Imports
Sometimes you import a module only to run it.
import "./setup.js";This is called a side-effect import.
It does not import names.
It just runs the module.
Use side-effect imports carefully because they can make behavior harder to trace.
Best Practices
Prefer named exports for utility functions:
export function formatDate(date) {}Use clear import paths:
import { formatDate } from "./formatters.js";Use aliases when they improve clarity:
import { format as formatUserName } from "./user.js";Keep imports at the top of the file.
Avoid unnecessary side-effect imports.
Common Mistakes
Mistake 1: Missing Curly Braces for Named Imports
import add from "./math.js";If add is a named export, use:
import { add } from "./math.js";Mistake 2: Forgetting the Relative Path Prefix
import { add } from "math.js";For a local file, use:
import { add } from "./math.js";Mistake 3: Importing a Name That Was Not Exported
import { divide } from "./math.js";This only works if math.js exports divide.
Summary
export shares code from a module.
import brings code into another module.
- Named exports are imported with curly braces.
- Names must match unless you use
as. - Namespace imports collect named exports into an object.
- Local import paths usually start with
./or../. - Static imports must be at the top level.
- Imported bindings are read-only from the importing file.
- Side-effect imports run a module without importing names.