![]() |
As a JavaScript project grows, the code tends to become long, difficult to read, and complicated to maintain. Putting everything in a single file is not a good practice: it becomes easier to introduce errors and more difficult to reuse the code.
To solve these problems, JavaScript provides modules.
In this article, we'll see:
- what is a JavaScript module
- why modules are useful
- how to export and import code
- practical examples explained step by step
- how to use modules in the browser and in Node.js
What is a module in JavaScript
A module is simply a JavaScript file that:
- contains isolated code
- exposes only what it decides to make public
- can be imported into other files
Each module has its own scope, meaning the variables defined within it are not visible externally unless they are explicitly exported.
👉 This avoids name conflicts and makes the code More secure and organized.
Why use modules
The main advantages of modules are:
1. Code organization
You can separate your code into logical files:
- a file for mathematical functions
- a file for user management
- a file for interface logic
2. Reuse
The same module can be imported into multiple places in the project.
3. Maintainability
If you need to change a feature, you know exactly where to intervene.
4. Avoiding Global Variables
Global variables are one of the most common causes of bugs in JavaScript.
How Modules Work: Export and Import
JavaScript modules are based on two keywords:
export→ to make something availableimport→ to use something exported from another file
First Simple Example
File: math.js
export function sum(a, b) {
return a + b;
}
Here we are:
- creating a
sum function
- exporting it with the
export keyword
This means that other files can use it.
File: main.js
import { sum } from "./math.js";
const result = sum(3, 5);
console.log(result);
Here we are:
- Importing the
sumfunction from themath.js - Using it as if it were defined in the same file
📌 The parentheses {} are needed because we are importing a named export.
Named exports
export function sum(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
import { sum, subtract } from "./math.js";
console.log(sum(10, 5));
console.log(subtract(10, 5));
⚠️ Important
You must use the same names used in the export.
Renaming an import
import { sum as addition } from "./math.js";
console.log(addition(2, 3));
This is useful for:
- avoiding name conflicts
- making code more readable
Exporting variables and constants
export const PI = 3.14159;
import { PI } from "./math.js";
console.log(PI);
Default export
export default function greet(name) {
return `Hello, ${name}!`;
}
import greet from "./saluta.js";
console.log(greet("Marco"));
📌 Important note:
- You don't need
{} - You choose the name - we could have also written:
import say_saluta from "./saluta.js";
Difference between normal and default export
| Type | Number | Import |
|---|---|---|
| named export | more than one | with {} |
| default export | only one | without {} |
Importing an entire module
import * as math from "./math.js";
console.log(math.sum(4, 6));
console.log(math.subtract(8, 3));
Here:
mathis an object- each export becomes a property
Modules in the browser
To use modules in the browser, you must:
- use separate files
- declare the
moduletype in the script
<script type="module" src="main.js"></script>
📌 Without type="module":
importandexportdo not work
Important features of modules
1. Automatic strict mode
Modules are always in strict mode, even without writing it.
2. Load only once
A module is loaded only once, even if imported multiple times.
3. Mandatory paths
"./file.js"
Why you should write "./file.js" in the browser
import follows URL rules, not those typical of traditional programming languages (this is the key point to understand).How the browser interprets an import
When the browser encounters a statement like this:import { sum } from "file.js";
"file.js" as “a file in the same folder”.Instead, it interprets it as:
- the name of an external resource
- a possible package
- a context-dependent absolute path
What does "./file.js" mean
import { sum } from "./file.js";
The ./ prefix explicitly tells the browser:
"Start from the file's folder current”
It's the same logic as file system paths:
./→ current folder../→ previous folder/→ site root
Concrete example
Project structure:
/project
├─ index.html
└─ js
├─ main.js
└─ math.js
Inside main.js:
import { sum } from "./math.js";
In this case:
main.jsandmath.jsare in the same folder./math.jsis the pathorretto
What happens if you don't use "./"
If you write:
import { sum } from "math.js";
The browser tries to search for the file as if it were:
https://yoursite.com/math.js
Since the file isn't there, the result is a 404 error.
More complex relative paths
If the file is in a different folder:
import { sum } from "../utils/math.js";
This It means:
- go up one folder
- enter the
utils folder
- load
math.js
Why "./" is often not needed in Node.js
In Node.js, it's common to see:
import express from "express";
This works because Node.js has a module resolution system that:
- looks for packages in
node_modules - recognizes modules by name
The browser, on the other hand:
- doesn't know
node_modules - doesn't know what a package is
- only uploads files via URL
Bundlers and build tools
Tools like Webpack, Vite, or Rollup:
- mimic Node.js behavior
- transform imports into real paths
- allow you to use package names
But this happens before the code reaches the browser.
Key rule to remember
In the browser, every import must be a valid URL.
Valid examples:
./file.js../file.js/scripts/file.jshttps://example.com/file.js
Summary
- The browser uses URLs, not logical names
"file.js"alone is not a valid relative path"./file.js"explicitly specifies the current folder- Node.js and bundlers follow different rules
- The path must always be specified in the browser
Real-world example: organizing a project
/src
├─ utils.js
├─ user.js
└─ main.js
// utils.js
export function formatName(name) {
return name.toUpperCase();
}
// user.js
import { formatName } from "./utils.js";
export function createUser(name) {
return {
name: formatName(name)
};
}
// main.js
import { createUser } from "./user.js";
const user = createUser("Luca");
console.log(user);
Conclusion
Modules are an essential foundation of modern JavaScript. They allow you to:
- write cleaner code
- avoid common mistakes
- build scalable applications
Understanding modules well means taking a big step forward in JavaScript development, whether for small projects or complex applications.
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment
