この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 他ファイルの関数読み込み
SEOタイトル: JavaScript モジュール完全ガイド(ES Modules import / export / CommonJS / 名前付き / デフォルト)

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>JavaScript で他ファイルの関数を読み込むには <strong>ES Modules (ESM)</strong> または <strong>CommonJS</strong> を使う</li><li>ES Modules: <code>export</code> / <code>import</code> 構文。<strong>ブラウザ / Node.js の標準</strong></li><li>CommonJS: <code>module.exports</code> / <code>require()</code>。<strong>Node.js 旧来の方式</strong>、まだ広く現役</li><li><strong>名前付き export</strong> は複数定義可、<strong>default export</strong> は 1 ファイル 1 つ</li><li>読み込み形式の指定: 拡張子 <code>.mjs</code> / package.json の <code>"type": "module"</code> で ESM、それ以外は CJS (Node)</li></ul></td></tr></table>
<h2>JavaScript のモジュールシステム</h2>

<p>JavaScript で「他のファイルに書いた関数」を呼び出すには<strong>モジュール</strong>機構を使います。現在は次の 2 方式が混在しています。</p>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>方式</th><th>構文</th><th>主な環境</th></tr></thead>
<tbody>
<tr><td><strong>ES Modules (ESM)</strong></td><td><code>import</code> / <code>export</code></td><td>ブラウザ・モダン Node.js (推奨)</td></tr>
<tr><td><strong>CommonJS (CJS)</strong></td><td><code>require()</code> / <code>module.exports</code></td><td>従来の Node.js</td></tr>
</tbody>
</table>

<p>新規プロジェクトは ESM が標準。既存の Node.js コードでは CJS が現役です。</p>

<h2>ES Modules &mdash; export</h2>

<h3>名前付き export</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// math.js
export function add(a, b) {
    return a + b;
}

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

export const PI = 3.14159;</code></pre>
<h3>default export</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// greet.js
export default function greet(name) {
    return `Hello, ${name}!`;
}</code></pre>
<p>1 ファイルに 1 つだけ。「このモジュールが提供するメイン機能」を表します。</p>

<h2>ES Modules &mdash; import</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// main.js

// 名前付き import
import { add, sub, PI } from &apos;./math.js&apos;;

console.log(add(2, 3));   // 5
console.log(PI);          // 3.14159

// default import (任意の名前を付けられる)
import greet from &apos;./greet.js&apos;;
console.log(greet(&apos;Alice&apos;));

// まとめて import
import * as math from &apos;./math.js&apos;;
console.log(math.add(1, 2));

// エイリアス
import { add as plus } from &apos;./math.js&apos;;
console.log(plus(2, 3));

// 副作用だけ実行 (return 値を使わない)
import &apos;./setup.js&apos;;</code></pre>
<h2>CommonJS &mdash; module.exports / require</h2>

<p>Node.js が伝統的に使ってきた方式。ファイル拡張子 <code>.js</code> でかつ package.json に <code>"type": "module"</code> がない場合の Node.js では<strong>こちらが標準</strong>です。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// math.js (CommonJS)
function add(a, b) { return a + b; }
function sub(a, b) { return a - b; }

module.exports = { add, sub, PI: 3.14159 };

// または
exports.add = add;
exports.sub = sub;</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// main.js (CommonJS)
const { add, sub, PI } = require(&apos;./math.js&apos;);

console.log(add(2, 3));   // 5

// オブジェクトをまるごと
const math = require(&apos;./math.js&apos;);
console.log(math.add(1, 2));</code></pre>
<h2>ESM と CJS の使い分け</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>観点</th><th>ESM</th><th>CJS</th></tr></thead>
<tbody>
<tr><td>構文</td><td><code>import / export</code></td><td><code>require / module.exports</code></td></tr>
<tr><td>非同期/同期</td><td>非同期(ロード時に静的解析)</td><td>同期</td></tr>
<tr><td>循環参照</td><td>サポート (一部制約あり)</td><td>サポート (壊れやすい)</td></tr>
<tr><td>Tree Shaking</td><td>○ (未使用 export を削除)</td><td>×</td></tr>
<tr><td>ブラウザ</td><td>○ (ネイティブ対応)</td><td>× (バンドラ必須)</td></tr>
<tr><td>__dirname / __filename</td><td>使えない (import.meta.url 経由)</td><td>使える</td></tr>
</tbody>
</table>

<h2>Node.js での ESM 有効化</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-json">// package.json
{
  "name": "myapp",
  "type": "module",
  "main": "index.js"
}</code></pre>
<p><code>"type": "module"</code> を入れると、その配下の <code>.js</code> が ESM として扱われます。CJS を一部混ぜたい場合は<strong>そのファイルだけ <code>.cjs</code> 拡張子</strong>にします。逆に CJS プロジェクト内で 1 つだけ ESM にしたい場合は <code>.mjs</code>。</p>

<h2>ブラウザでの ESM</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- type="module" を付けるだけで ESM になる -->
<script type="module" src="./main.js"></script>

<!-- インラインでも OK -->
<script type="module">
    import { add } from &apos;./math.js&apos;;
    console.log(add(1, 2));
</script></code></pre>
<p>ブラウザの ESM では<strong>パスは相対 / 絶対 URL のみ</strong>。<code>'./math.js'</code> や <code>'/lib/math.js'</code> は OK、<code>'math.js'</code> や <code>'lodash'</code> (bare specifier)は基本不可(importmap 使用時除く)。</p>

<h2>動的 import</h2>

<p><strong>遅延読み込み</strong>や条件分岐で読み込む場合は <code>import()</code> 関数形式を使います(Promise を返す)。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// クリック時に初めて読み込む
button.addEventListener(&apos;click&apos;, async () => {
    const { showModal } = await import(&apos;./modal.js&apos;);
    showModal();
});

// 条件付き
if (user.isAdmin) {
    const admin = await import(&apos;./adminPanel.js&apos;);
    admin.render();
}</code></pre>
<p>動的 import はバンドラ (Webpack / Vite / Rollup) でも<strong>コード分割</strong>のトリガーとして使われます。</p>

<h2>FAQ</h2>

<p><strong>Q: <code>import</code> と <code>require</code> 混ぜていい?</strong><br />
A: Node.js では制約あり。ESM から CJS は <code>import x from 'cjsmodule'</code> でほぼ動く。CJS から ESM は<strong>動的 import()</strong> が必要。</p>

<p><strong>Q: <code>__dirname</code> が ESM で使えない</strong><br />
A: <code>import.meta.url</code> を使う。<code>const __dirname = path.dirname(fileURLToPath(import.meta.url));</code></p>

<p><strong>Q: ファイル拡張子は省略できる?</strong><br />
A: Node.js の ESM は<strong>拡張子必須</strong>(<code>./math.js</code>)。CJS / バンドラでは省略可。</p>

<p><strong>Q: TypeScript ではどっち?</strong><br />
A: ソース上は <code>import/export</code> で書き、<code>tsconfig.json</code> の <code>module</code> オプションで出力先を選ぶ(ESNext / CommonJS / NodeNext など)。</p>