Learn JavaScript - ES Modules and Using import/export
Episode 10 of 23

Learn JavaScript - ES Modules and Using import/export

This episode covers splitting code into modules: named exports and default exports, how to import in various forms, and running ES modules in Node.js with the right package.json. You also understand why modules matter for growing projects.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Imagine writing an entire application in a single file with thousands of lines. Soon you won't know which function is called from where, and changing one part risks breaking another. Modules are the solution: splitting code into small files, each responsible for one part, then sharing code between them via import and export.

Episode 10 covers ES modules — JavaScript's official module system since ES6. You'll learn named exports and default exports, the various forms of the import statement, and how to run modules correctly in Node.js. Modules also prepare you for episodes 20 and 21 about tooling and bundlers.

One concept makes it all make sense: export determines what leaves a file, and import determines what enters another file.

Why Modules Are Needed

The Problem of Single-File Code

Without modules, all code shares one global namespace. The risk is real: two files could accidentally define functions with the same name, and the later one overwrites the earlier one. Errors like this are very hard to track because no error appears.

Modules solve this with two mechanisms:

  • Isolated scope: each file has its own scope; variables inside it are invisible from outside unless exported.
  • Explicit dependencies: a file only receives what it imports, so the code flow is clearly visible.

As a result, code is easier to search, test, and reuse. One focused module is far easier to read than one file trying to do everything.

Named Exports and Imports

Exporting Multiple Values

Named exports export many values from one file with clear names. Each value is marked with the export keyword:

JSmatematika.js - named exports
export const PI = 3.14159;
 
export function lingkaran(jariJari) {
  return 2 * PI * jariJari;
}
 
export function luasLingkaran(jariJari) {
  return PI * jariJari * jariJari;
}

The matematika.js file above exports the PI constant and two functions. export const PI = 3.14159 makes the value available to other files. With named exports, the name in the destination file must match the name in the source file exactly.

Importing Named Exports

To use the exported values, use import with curly braces:

JSmain.js - importing named exports
import { PI, luasLingkaran } from "./matematika.js";
 
console.log(PI);
console.log(luasLingkaran(7));

import { PI, luasLingkaran } from "./matematika.js" takes only the values you need. Notice the path starts with ./ and ends with .js — this rule is mandatory in Node.js. The advantage of named exports: the IDE can find all users of a function, and only imported code is loaded.

Aliasing Imports

If a name conflicts in the destination file, use an alias with the as keyword:

JSImport with an alias
import { luasLingkaran as hitungLuas } from "./matematika.js";
 
console.log(hitungLuas(7));

import { luasLingkaran as hitungLuas } gives a new local name without changing the original name in the source file. Aliases are also used to rename for clarity in the destination file's context.

Default Exports and Imports

One Main Export per Module

A default export is used for one main value per file. The default value doesn't have to have a name in the source file:

JSsapa.js - default export
export default function sapa(nama) {
  return `Halo, ${nama}!`;
}

export default function sapa(nama) exports this function as the module's default value. A module may only have one default export. This pattern fits when a file represents one component or one main function.

Importing Default Exports

Default imports don't use curly braces, and the local name is free — it doesn't have to follow the original name:

JSmain.js - importing the default
import sapaDariFile from "./sapa.js";
 
console.log(sapaDariFile("Arman"));

import sapaDariFile from "./sapa.js" gives a local name that can be anything. The rule of thumb: curly braces for named exports, no curly braces for default exports. Both can also be combined in a single import statement.

Running ES Modules in Node.js

Marking a Project as a Module

Node.js needs to know whether a file uses ES modules or CommonJS. The simplest way: add "type": "module" to package.json:

package.json with module type
{
  "name": "belajar-modul",
  "type": "module",
  "main": "main.js"
}

With "type": "module", Node treats all .js files as ES modules. Without it, Node assumes CommonJS and import will error with SyntaxError: Cannot use import statement outside a module.

Running a Module

After package.json is set up, run the main file as usual:

Running an ES module
node main.js

node main.js executes main.js, which imports from matematika.js and sapa.js. Node handles module resolution automatically, including nested imports: if main.js imports matematika.js, and matematika.js imports another module, everything gets loaded too.

Re-exporting from Several Files

You can also consolidate exports through a single barrel file to simplify imports in many places:

JSindeks.js - re-exports
export { lingkaran, luasLingkaran, PI } from "./matematika.js";
export { default as sapa } from "./sapa.js";

export { lingkaran } from "./matematika.js" forwards another file's exports without redefining them. Other files just import from one place: import { sapa, luasLingkaran } from "./indeks.js".

Warning

The two most common import mistakes: forgetting the .js extension in local module paths, and forgetting "type": "module" in package.json. Both surface confusing errors even though the cause is simple. Check these two things first before debugging further.

Wrap-Up

Episode 10 enabled you to split code into modules: named exports for many values, default exports for one main value, various import forms, and running ES modules in Node.js with "type": "module". You also learned the barrel pattern for consolidating exports.

Key takeaways:

  • Modules isolate scope and make dependencies explicit.
  • Named exports use curly braces on import and names must match.
  • Default exports have no curly braces and can be named freely locally.
  • One module may only have one default export.
  • Add "type": "module" so Node processes ES modules.
  • Local module paths must start with ./ and end with .js.

In the next episode 11 we'll cover destructuring and structured assignment — extracting values from arrays and objects directly into variables with one tidy statement. This feature makes your code far more concise and clearer to read.

Learn JavaScript - ES Modules and Using import/export | Learn JavaScript