Jamie Balfour

Welcome to my personal website.

Find out more about me, my personal projects, reviews, courses and much more here.

Part 6.6Modules in JavaScript

JavaScript modules provide a way to divide an application into smaller files. Each file can focus on one responsibility and share only the values or functions that other parts of the application need.

Modules are a fundamental part of modern JavaScript. They are used in browser applications, Node.js and frameworks such as React.

This page uses the standard ECMAScript module syntax, often called ES modules or ESM.

What modules are

A module is a JavaScript file that can export values for other files to use. Another module can then import those values.

For example, a file named config.js could export the name of a website:

config.js
export const siteName = "Example";

A second file can import siteName and use it as though it had been declared locally.

app.js
import { siteName } from "./config.js";

console.log(siteName);
Output
Example

Why modules are useful

Placing an entire application in one file quickly makes the code difficult to navigate. Modules allow related code to be grouped into logical files.

A project might be organised as follows:

Project structure
project/
├── index.html
└── scripts/
    ├── app.js
    ├── calculations.js
    └── formatting.js

This makes functionality easier to locate, test and reuse. Values declared inside a module also remain within that module unless they are explicitly exported, which helps prevent accidental naming conflicts.

Exporting values

Add the export keyword to a declaration to make that value available to other modules.

config.js
export const taxRate = 20;
export const currency = "GBP";

Only exported values can be imported elsewhere. Other declarations remain private to the module.

Exporting functions

Functions can be exported in exactly the same way as other values.

calculations.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

Exporting a function does not run it. The function runs only when another part of the program calls it.

Named exports

A module may contain several named exports. They can be exported as they are declared, or collected into an export statement at the end of the file.

maths.js
const pi = 3.14159;

function square(number) {
  return number * number;
}

export { pi, square };

These are called named exports because each value is imported using its exported name.

Default exports

A module can have one default export. A default export normally represents the main value provided by that file.

UserCard.js
export default function UserCard() {
  return "User";
}

A file may contain both a default export and named exports, although keeping a module focused usually makes it easier to understand.

Importing named exports

Named exports are imported between braces. Their names must match the names used by the exporting module.

app.js
import { pi, square } from "./maths.js";

console.log(pi);
console.log(square(4));
Output
3.14159
16

Importing default exports

A default import does not use braces. Because the export is the default value, the importing module can choose its local name.

app.js
import UserCard from "./UserCard.js";

In practice, using a name that matches the exported function or component makes the code easier to follow.

Import aliases

The as keyword gives a named import a different local name. This is useful when two modules export values with the same name or when a more descriptive name is needed.

app.js
import { square as squareNumber } from "./maths.js";

console.log(squareNumber(5));
Output
25

Modules in the browser

To use modules directly in a web page, set the script element's type attribute to module.

index.html
<script type="module" src="./scripts/app.js"></script>

Browser module paths should normally begin with ./ or ../. Including the .js file extension also avoids ambiguity when the browser resolves the path.

Modules loaded from local files may be restricted by the browser. During development, serve the project through a local web server rather than opening the HTML file directly.

Modules in React

React applications are typically built from many small modules. Components are commonly defined in one file and imported into another.

UserCard.jsx
export default function UserCard() {
  return <p>Jamie</p>;
}
App.jsx
import UserCard from "./UserCard.jsx";

function App() {
  return <UserCard />;
}

export default App;

The build tools used by React projects process these imports and combine the required modules for the browser. For more information, see the React course.

Common module errors

Most problems with modules are caused by confusing named and default exports, or by using an incorrect file path.

  • Use braces when importing a named export.
  • Do not use braces when importing a default export.
  • Check that relative paths begin with ./ or ../.
  • Check the spelling and capitalisation of file and export names.
  • Remember that a module can contain only one default export.
Named and default imports
// Named export: use braces
import { square } from "./maths.js";

// Default export: do not use braces
import UserCard from "./UserCard.js";

When to use modules

Use modules whenever code can be separated into clear responsibilities. A module might contain a group of related calculations, formatting functions, configuration values or one React component.

Avoid splitting every small function into its own file without a reason. A useful module should have a clear purpose and a name that explains that purpose.

Modules make applications easier to navigate, maintain, test and reuse. They also provide the structure needed as a JavaScript project grows beyond a single file.

Feedback 👍
Comments are sent via email to me.