Modular JavaScript: Writing Clean, Maintainable, and Scalable Code
As JavaScript applications grow in size and complexity, organizing code into modules becomes essential. ES6 introduced a native module system that allows developers to break code into separate files and reuse it with clean import
and export
syntax.
In this module, we’ll explore what modules are, how they work, and best practices to use them effectively.
Table of Contents
- What Are Modules in JavaScript?
- Benefits of Using Modules
export
Statementimport
Statement- Default Exports vs Named Exports
- Combining Named and Default Exports
- Modules in Browser vs Node.js
- Using Modules in HTML
- Module Scope
- Best Practices
- Conclusion
1. What Are Modules in JavaScript?
A module is a file that contains reusable code. Instead of putting everything in one file, you split logic across multiple files and import/export functionality as needed.
2. Benefits of Using Modules
- Encourages code reuse
- Improves readability and maintainability
- Avoids global scope pollution
- Enables lazy loading and better performance
- Facilitates team collaboration
3. export
Statement
To make something available outside a file, you use export
.
// math.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
You can export variables, functions, or classes.
4. import
Statement
To use exported code in another file:
// main.js
import { add, multiply } from './math.js';
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
The file path must be relative and include the .js
extension when used in browsers.
5. Default Exports vs Named Exports
Named Export (can export multiple things):
export const greet = () => console.log("Hi");
export const PI = 3.14;
Import like:
import { greet, PI } from './utils.js';
Default Export (only one per file):
// logger.js
export default function log(msg) {
console.log(msg);
}
Import like:
import log from './logger.js';
You can name the default import anything.
6. Combining Named and Default Exports
// lib.js
export const version = "1.0.0";
export default function sayHello() {
console.log("Hello!");
}
// main.js
import sayHello, { version } from './lib.js';
7. Modules in Browser vs Node.js
- Browser: Use ES Modules with
<script type="module">
. - Node.js: Use
import/export
in.mjs
files or enable"type": "module"
inpackage.json
.
<!-- index.html -->
<script type="module" src="main.js"></script>
Modules are deferred by default, so no need to add defer
.
8. Using Modules in HTML
If you’re working with front-end JavaScript:
<!-- main.js -->
import { sayHi } from './greetings.js';
sayHi("Ravi");
<!-- index.html -->
<script type="module" src="main.js"></script>
Make sure your files are served over HTTP (not just opened with file://
) due to CORS restrictions.
9. Module Scope
Every module has its own scope. Variables and functions defined inside a module are not accessible outside unless explicitly exported.
// helper.js
const secret = "12345"; // not exported
export const reveal = () => "The secret is hidden.";
10. Best Practices
- Group related functions into modules.
- Use default export for primary functionality and named exports for helpers.
- Keep module files small and focused.
- Avoid circular dependencies.
- Use index files to simplify imports.
Example index.js
:
export * from './math.js';
export * from './string.js';
Now import everything from one place:
import { add, capitalize } from './utils/index.js';
11. Conclusion
JavaScript modules bring structure and reusability to your codebase. They’re essential for building modern applications, and you’ll find them in every serious JavaScript project.
Next up: JavaScript Event Loop, Call Stack, and Concurrency Explained