๐Ÿ“˜ Blog 7: JavaScript Modules: Organizing and Reusing Code with import and export


As web applications grow in size and complexity, managing your code efficiently becomes crucial. JavaScript modules allow you to split code into smaller, reusable pieces with clean separation of concerns. With ES6 (ECMAScript 2015), JavaScript introduced a standardized module system that is now widely supported in modern browsers and JavaScript environments.

In this seventh blog of the JavaScript Essentials series, weโ€™ll take a deep dive into ES6 modulesโ€”what they are, how to use them, and how they help you write cleaner, scalable, and maintainable code.


1. What Are JavaScript Modules?

A module is a file that encapsulates related pieces of code. Variables, functions, and classes declared in one module are not globally accessibleโ€”they must be exported to be used in other modules.

Why use modules?

  • Avoid global scope pollution
  • Separate logic by responsibility
  • Reuse code across files/projects
  • Improve testability and maintainability

2. Exporting from a Module

There are two ways to export values: named exports and default exports.

Named Exports

// math.js
export const PI = 3.14;
export function add(x, y) {
  return x + y;
}

Default Export

// greet.js
export default function(name) {
  return `Hello, ${name}!`;
}

You can also export all at once:

const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
export { multiply, divide };

3. Importing Modules

Named Imports

import { PI, add } from './math.js';
console.log(add(3, PI));

Default Import

import greet from './greet.js';
console.log(greet("Alice"));

Renaming Imports

import { add as sum } from './math.js';

Import Everything

import * as MathUtil from './math.js';
console.log(MathUtil.PI);

4. Module Scope and Encapsulation

Modules help avoid variable leaks by default. Variables defined in a module file arenโ€™t visible to other modules unless exported.

// module.js
let privateVar = 'hidden';
export const publicVar = 'visible';

Trying to access privateVar outside will result in an error.


5. Using Modules in HTML

Use the type="module" attribute when referencing module files in the browser.

<script type="module" src="main.js"></script>

Important notes:

  • Module scripts are deferred automatically
  • Scripts must use file paths (./module.js)
  • Cross-origin restrictions apply for loading modules

6. Live Bindings

Module exports are live bindingsโ€”they reflect the current value.

// counter.js
export let count = 0;
export function increment() {
  count++;
}
// main.js
import { count, increment } from './counter.js';
increment();
console.log(count); // Output: 1

7. Dynamic Imports with import()

Dynamic imports allow loading a module conditionally or on demand.

if (shouldLoadFeature) {
  import('./feature.js')
    .then(module => module.init())
    .catch(err => console.error(err));
}

This is useful for:

  • Lazy loading
  • Code splitting
  • Loading large libraries on demand

8. Top-Level await in Modules

As of ES2022, you can use await at the top level in modules (not inside functions).

// data.js
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);

Must be inside a module script (type="module").


9. Importing JSON and Non-JS Files

ES Modules in browsers donโ€™t support importing JSON or CSS directly, but tools like Webpack, Vite, and Rollup do.

// With Webpack
import config from './config.json';
import './style.css';

10. Real Project Structure Example

Organize your code logically by feature or domain.

/src
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ navbar.js
โ”‚   โ””โ”€โ”€ footer.js
โ”œโ”€โ”€ utils/
โ”‚   โ””โ”€โ”€ math.js
โ”œโ”€โ”€ main.js

navbar.js

export function createNavbar() {
  const nav = document.createElement('nav');
  nav.textContent = "Navigation";
  return nav;
}

main.js

import { createNavbar } from './components/navbar.js';
document.body.appendChild(createNavbar());

11. Best Practices

โœ… Export only whatโ€™s needed
โœ… Use named exports when exporting multiple utilities
โœ… Keep modules small and focused
โœ… Use consistent naming and folder structure
โœ… Avoid circular dependencies


12. Common Pitfalls

โŒ Missing file extensions

import utils from './utils'; // โŒ fails
import utils from './utils.js'; // โœ…

โŒ Mixing CommonJS (require) with ES Modules

โŒ Global variables in modules โ€” avoid polluting scope


13. Summary Table

FeatureDescription
exportMakes values accessible to other files
importImports values from another module
default exportA single main export per file
named exportAllows multiple exports from one module
type=\"module\"Enables module use in HTML
import()Dynamic, asynchronous import
Top-Level awaitUse await directly in modules

14. Sample Application Snippet

math.js

export function square(x) {
  return x * x;
}

main.js

import { square } from './math.js';
console.log(`Square of 4 is ${square(4)}`);

index.html

<script type="module" src="main.js"></script>

15. Conclusion

JavaScript modules are a fundamental building block for scalable application development. By organizing code into reusable, well-structured modules, you enhance clarity, maintainability, and reusability across your project.

In the next blog, weโ€™ll cover Debugging and Error Handling in JavaScriptโ€”including try...catch, browser tools, stack traces, and strategies to write more robust, bug-resistant code.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top