CODE MODULARITY AND MODULES IN JAVASCRIPT
Code modularity means splitting code into separate files where each file is responsible for one part of the project.
This note explains code modularity and ECMAScript modules in simple language.
You will learn:
- what code modularity is
- why modules are useful
- what ECMAScript Modules are
- what default export and import mean
- what named export and import mean
- how renaming works
- what namespace import is
- how local images are imported in Vite projects
1. What is code modularity?
As a project grows, one file is no longer enough.
Developers split code into separate files, where each file is responsible for one part of the project. This is called code modularity.
A module is usually one JavaScript file that contains a specific piece of logic and can be used in other files.
Diagram 1. From one big file to modules
Big project
-> too much code in one file
-> split code into smaller files
-> each file handles one job
Instead of putting everything in one place, we divide the code into logical parts. That makes the project easier to understand.
2. Why modularity is useful
Modules have three main advantages:
- maintainability
- namespace protection
- reusability
Maintainability
A good module should depend as little as possible on other parts of the project.
This means:
- one module is easier to update
- changing one part is less likely to break the whole project
- testing is easier
Namespace
Global variables can create conflicts. If unrelated files use the same global names, problems appear.
Modules help avoid this because each module has its own scope.
Reusability
A module can be reused in different places or even in different projects.
This is better than copying old code again and again and editing it manually.
Diagram 2. Why modules are useful
Modules
|
|- easier to maintain
|- protect namespace
`- easier to reuse
This is the main reason modules are so important in modern JavaScript.
3. What are ECMAScript Modules?
ECMAScript Modules, or ESM, are the modern JavaScript module system.
They define a standard way to:
- export values from one file
- import those values into another file
In simple words:
One file can share something
Another file can use it
Diagram 3. Main idea of ESM
Module A
-> exports value
Module B
-> imports value
-> uses that value
Modules communicate through export and import.
4. Module example
makeMessage.js
export default function makeMessage(username) {
return `Welcome, ${username}!`;
}
index.js
import makeMessage from "./makeMessage";
console.log(makeMessage("Jacob")); // "Welcome, Jacob!"
This means:
makeMessage.jsshares a functionindex.jstakes that function and uses it
Diagram 4. Module connection
makeMessage.js
-> exports function
index.js
-> imports function
-> calls function
5. Important idea about modules
Each JavaScript file works in its own module context.
That means:
- it has its own scope
- it imports what it needs
- it exports what other files may use
Diagram 5. Each file is its own module
File 1
-> own module scope
File 2
-> own module scope
They connect only through import/export
This helps keep code organized and safer.
6. Default export
A module can have one default export.
This is usually the main value of the file.
The syntax is:
export default exportedValue
Example of default export
const makeMessage = username => {
return `Welcome, ${username}!`;
};
export default makeMessage;
Here, makeMessage is the main thing exported from the file.
Diagram 6. Default export
One module
-> one main exported value
-> default export
Easy rule:
default export = the main thing from this file
7. Default import
To import a default export, use:
import name from "..."
Example
import makeMessage from "./makeMessage";
console.log(makeMessage("Jacob"));
Important detail: the imported name can be chosen freely.
So this also works:
import createMessage from "./makeMessage";
It still works because it is a default import.
Diagram 7. Default import
export default makeMessage
-> import anyName from "./makeMessage"
With default import, the local variable name is your choice.
8. Named export
A named export is used when a module exports one or more values with specific names.
Syntax:
export exportedValue
Example
export const makeMessage = username => {
return `Welcome, ${username}!`;
};
export const levels = ["easy", "medium", "hard"];
Here the module exports:
makeMessagelevels
Diagram 8. Named exports
One module
|
|- export makeMessage
`- export levels
Unlike default export, a module can have many named exports.
9. Named import
To import named exports, use curly braces:
import { name } from "..."
Example
import { makeMessage, levels } from "./makeMessage";
console.log(makeMessage("Jacob"));
console.log(levels);
Important rule: for named import, the names must match the exported names.
Diagram 9. Named import
Module exports:
makeMessage
levels
Import:
{ makeMessage, levels }
Easy rule:
named export = fixed name
named import = same name
10. Default export vs named export
This is one of the most important differences.
Default export
- only one per module
- imported without curly braces
- imported name can be changed freely
Named export
- many per module are possible
- imported with curly braces
- imported name must match the exported name unless renamed
Diagram 10. Default vs named
Default export
-> one main value
-> import without {}
Named export
-> many values possible
-> import with {}
11. Renaming during import
Sometimes the imported name is too long, too general, or conflicts with a variable name in the current file.
Then you can rename it with:
import { name as newName } from "..."
Example
export const original = "Hello, World!";
import { original as renamed } from "./myModule.js";
console.log(renamed); // "Hello, World!"
Diagram 11. Renaming
Exported name:
original
Imported name:
renamed
The value stays the same. Only the local variable name changes.
12. When renaming is useful
Renaming is useful when:
- the imported name is too general
- the imported name is too long
- the imported name conflicts with a name in the current file
Diagram 12. Why rename
Imported name problem
|
|- too general
|- too long
`- name conflict
Solution
-> use as
13. Namespace import
Namespace import means importing all named exports from a module as one object.
Syntax:
import * as everything from "..."
Example
export const name = "Mango";
export const age = 26;
export const email = "mango@mail.com";
import * as user from "./myModule.js";
console.log(user.name); // "Mango"
console.log(user.age); // 26
console.log(user.email); // "mango@mail.com"
Diagram 13. Namespace import
Module exports many named values
-> import * as user
-> all values become properties of user object
Now you access everything through dot notation.
14. Why namespace import is useful
Namespace import is useful when:
- a module has many named exports
- you want to group them into one object
- you want to avoid name conflicts in the current file
Diagram 14. Namespace import idea
Many exports
-> one namespace object
-> cleaner access with dot notation
15. Local images in Vite projects
In regular HTML, images are often used through relative paths.
But in projects built with bundlers like Vite, local images are usually imported as modules.
Why?
Because the bundler:
- analyzes the project
- combines files
- optimizes resources
- generates the correct final paths automatically
Diagram 15. Bundler and images
Local image in project
-> import image in JavaScript
-> bundler generates correct final path
-> use that path in src
This helps avoid path problems in builds and deployment.
16. Importing a local image
Example:
import catImage from "./images/cat.jpg";
Here:
catImagebecomes a string- that string contains the correct image path generated by the bundler
- you do not need to calculate the final path manually
Diagram 16. Image import flow
./images/cat.jpg
-> import
catImage
-> string with ready path
17. Why this image import method is useful
This approach helps:
- avoid path errors
- work correctly in production builds
- use images in dynamic JavaScript code
- pass image paths into components, variables, and configuration
Diagram 17. Why import images
Import image as module
-> safer paths
-> works with bundler
-> easy to use in JavaScript
18. Easy memory rules
Module = one JavaScript file with code
export = share something
import = use something from another file
default export = one main value
named export = one or more specific values
as = rename during import
* as = namespace import
Vite image import = local image becomes module path
19. Quick summary
- Code modularity means splitting code into separate files by functionality.
- Modules improve maintainability, namespace safety, and reusability.
- ECMAScript Modules are the modern JavaScript module system.
- A module can have one default export.
- A module can have many named exports.
- Default imports do not use curly braces and can use any local name.
- Named imports use curly braces and normally keep the exported name.
- Renaming uses
as. - Namespace import uses
import * as .... - In Vite projects, local images are imported as modules so the bundler can generate the correct final path.
20. Final conclusion
If you understand these ideas:
modularity
module
export
import
default export
named export
renaming
namespace import
image import in Vite
then you already have a strong foundation for working with modules in modern JavaScript.
Modules are one of the most important parts of real frontend development because they help keep projects clean, scalable, and easier to maintain.