モジュールの考え方(まず全体像から)
モジュールは、「ファイルごとに役割を分けて、必要なものだけをやり取りする仕組み」です。
1ファイル = 1モジュール、と考えておけばOKです。
- 「このファイルから外に出すもの」を
exportする - 「他のファイルから持ってくるもの」を
importする
というルールで、コードをきれいに分割していきます。
// math.js (モジュール)
// 外に出したい関数を export
export function add(a, b) {
return a + b;
}
JavaScript// main.js (別モジュール)
// 他のファイルから関数を import
import { add } from "./math.js";
console.log(add(2, 3)); // 5
JavaScriptここが重要です。
「export されたものだけが、他のファイルから使える」
export されていない変数や関数は、そのファイルの中だけの「内緒」です。
export の基本(何を外に出すか決める)
名前付き export(複数 export したいときの基本形)
一番よく使うのが「名前付き export」です。export を付けたものだけが、そのモジュールの「公開API」になります。
// math.js
export const PI = 3.14;
export function add(a, b) {
return a + b;
}
export function sub(a, b) {
return a - b;
}
// これは export していないので外から見えない
const secret = "hidden";
JavaScriptこのファイルでは、PI, add, sub の3つが外に出ていて、secret は中だけの存在です。
あとからまとめて export する書き方もあります。
// math.js
const PI = 3.14;
function add(a, b) { return a + b; }
function sub(a, b) { return a - b; }
export { PI, add, sub }; // まとめて export
JavaScriptデフォルト export(そのモジュールの「主役」を1つだけ)
1つのモジュールに「これがメイン!」というものがある場合、export default を使えます。
各モジュールにつき、default は1つだけです。
// greet.js
export default function greet(name) {
console.log(`Hello, ${name}`);
}
JavaScript変数でもクラスでもOKです。
// User.js
export default class User {
constructor(name) {
this.name = name;
}
}
JavaScriptここが重要です。
名前付き export は何個でも OK、default export は1つだけ。
default は「このファイルの看板」のようなものです。
import の基本(他のファイルから使わせてもらう)
名前付き import({} で指定して持ってくる)
名前付き export を持ってくるときは、{} を使います。
// math.js
export const PI = 3.14;
export function add(a, b) { return a + b; }
export function sub(a, b) { return a - b; }
JavaScript// main.js
import { PI, add } from "./math.js";
console.log(PI); // 3.14
console.log(add(2, 3)); // 5
JavaScript{ PI, add } の部分の名前は、export 側の名前と一致している必要があります。
名前を変えて import したいときは as を使います。
import { add as plus } from "./math.js";
console.log(plus(2, 3)); // 5
JavaScriptdefault import(名前を自由につけて持ってくる)
default export を import するときは、{} なしで書きます。
// greet.js
export default function greet(name) {
console.log(`Hello, ${name}`);
}
JavaScript// main.js
import greet from "./greet.js";
// ↑ 好きな名前で OK
greet("Alice");
JavaScript同じ default export を、別のファイルで別名として import しても構いません。
import hello from "./greet.js";
hello("Bob");
JavaScriptここが重要です。
default import は {} を付けないで書き、名前は自由につけられる。
名前付き import は {} 付きで、名前を揃える(または as で変える)必要があります。
default と名前付きを同時に import する
1つのファイルから、default と名前付きの両方を export している場合もあります。
// user.js
export default class User {
constructor(name) {
this.name = name;
}
}
export function createGuest() {
return new User("Guest");
}
JavaScriptこれを import するときはこう書けます。
// main.js
import User, { createGuest } from "./user.js";
const u1 = new User("Alice");
const u2 = createGuest();
JavaScriptファイルパスと拡張子の扱い(つまずきポイント)
相対パスで指定する(./ や ../ から始まる)
ブラウザの ES モジュールでは、import のパスに必ず ./ や ../ を付けます。
import { add } from "./math.js"; // 同じフォルダ
import { add } from "../lib/math.js"; // 1つ上のフォルダ
JavaScript"math" のように書くと、ブラウザでは基本的にエラーになります(バンドラーなし前提)。
必ず "./xxx.js" のように書く習慣をつけてください。
拡張子 .js を付ける(ブラウザ ES モジュールの場合)
ブラウザで <script type="module"> を使う場合、基本的には .js 拡張子まで書きます。
import { add } from "./math.js"; // .js まで書く
JavaScriptNode.js やバンドラ(webpack, Vite など)を使うときは設定によって挙動が変わりますが、
初心者のうちは「ブラウザ ES モジュールでは .js まで書く」と覚えておけばOKです。
モジュールを使うと何が嬉しいのか(設計の視点)
ファイルごとに「責任」を分けられる
例えば、小さなアプリでも以下のように分けられます。
math.js:計算系の関数だけUser.js:ユーザークラスだけapi.js:サーバー通信だけmain.js:アプリ全体の入口(他モジュールを組み合わせる)
main.js では「全体の流れ」に集中でき、
細かい処理はそれぞれのモジュールに任せられます。
// api.js
export async function fetchUser(id) {
const res = await fetch(`/api/users/${id}`);
return await res.json();
}
JavaScript// main.js
import { fetchUser } from "./api.js";
async function main() {
const user = await fetchUser(1);
console.log(user);
}
main();
JavaScriptここが重要です。
モジュールは「クラス」よりも大きい単位での設計道具です。
「何がどのファイルにいるべきか」を決めることで、プロジェクト全体が整理されます。
内部の実装を隠し、外には「必要なものだけ」出す
export していないものはそのファイル内だけで完結する「内部実装」です。
// password.js
function hash(text) { // export しない → 内部専用
return `hash:${text}`;
}
export function createHashedPassword(raw) {
return hash(raw);
}
JavaScript外からは hash という関数があるかどうかも分かりません。
これはクラスのプライベートフィールドと同じ発想で、
「外から使わせたいもの(インターフェース)」と「内側のロジック」を分ける働きをします。
よくあるパターンと例題
例1:ユーティリティ関数モジュール
// stringUtils.js
export function capitalize(str) {
if (!str) return "";
return str[0].toUpperCase() + str.slice(1);
}
export function trimAll(str) {
return str.trim();
}
JavaScript// main.js
import { capitalize, trimAll } from "./stringUtils.js";
const raw = " alice ";
const name = capitalize(trimAll(raw));
console.log(name); // Alice
JavaScript例2:クラスを default export する
// User.js
export default class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(`こんにちは、${this.name} です`);
}
}
JavaScript// main.js
import User from "./User.js";
const u = new User("Alice");
u.greet();
JavaScript例3:設定オブジェクトを export する
// config.js
export const API_BASE_URL = "https://api.example.com";
export const DEFAULT_LANG = "ja";
JavaScript// main.js
import { API_BASE_URL, DEFAULT_LANG } from "./config.js";
console.log(API_BASE_URL, DEFAULT_LANG);
JavaScript実際の HTML でモジュールを使うときの注意(ブラウザ)
type=”module” を付ける
ブラウザで ES モジュールを使うときは、
HTML でこう書きます。
<script type="module" src="./main.js"></script>
HTMLmain.js の中で import / export を使えるようになります。
逆に、type="module" を付けずに import を書くとエラーになります。
まとめ
import / export の本質は、
「ファイル(モジュール)ごとに役割を分け、必要なものだけを明示的にやり取りする」 ことです。
押さえておきたいポイントを整理すると:
- 1ファイル = 1モジュール、と考える
- 他のファイルから使わせたいものに
exportを付ける- 名前付き export は
{}で import export defaultは1つだけ、名前を自由につけて import
- 名前付き export は
importでは必ずパスを書き、ブラウザ ES モジュールでは"./xxx.js"のように書く- export されていないものは、モジュール内だけの「内緒」
- モジュールごとに「何を担当させるか」を決めることで、設計が楽になる
最初は小さなプロジェクトでも、
「1ファイルに全部書く」のをやめて、
「クラスや関連する関数を1ファイルにまとめて、それを export / import で繋ぐ」
というところから始めてみてください。
それだけで、コードの見通しがかなり変わってきます。

