default export と named export

ES Modules には、default export(デフォルトエクスポート)と named export(名前付きエクスポート)の2種類のエクスポート方法があります。それぞれの特徴と使い分けを理解しましょう。

Named Export(名前付きエクスポート)

名前を付けて複数の値をエクスポートする方法です。1つのモジュールから複数の値を公開できます。

// utils.js
export const VERSION = "1.0.0";

export function formatDate(date) {
  return date.toLocaleDateString();
}

export function formatCurrency(amount) {
  return `¥${amount.toLocaleString()}`;
}
// インポート時は同じ名前を使う
import { VERSION, formatDate, formatCurrency } from './utils.js';

Default Export(デフォルトエクスポート)

モジュールの「メインの値」を1つだけエクスポートする方法です。1モジュールにつき1つだけ指定できます。

// User.js
export default class User {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    return `Hello, ${this.name}!`;
  }
}
// インポート時は任意の名前を付けられる
import User from './User.js';
import MyUser from './User.js'; // これも OK

2つの違い

項目Named ExportDefault Export
複数可1つだけ
インポート時の名前固定(as で変更可)自由
波括弧必要不要
Named Export

明示的な名前でエクスポートするため、インポート時に何を読み込んでいるか明確。IDE の補完も効きやすい。

Default Export

インポート時に任意の名前を付けられる柔軟性がある。1ファイル1クラス/1関数のパターンに適している。

併用する場合

1つのモジュールで両方を使用することもできます。

// api.js
export const BASE_URL = "https://api.example.com";
export const TIMEOUT = 5000;

export default async function fetchData(endpoint) {
  const response = await fetch(`${BASE_URL}${endpoint}`);
  return response.json();
}
// インポート
import fetchData, { BASE_URL, TIMEOUT } from './api.js';

どちらを使うべきか

使い分けの一般的なガイドラインを紹介します。

Named Export が適している場合

ユーティリティ関数の集まり、複数の定数、複数のコンポーネントなど、モジュールが複数の関連する値を持つ場合。

Default Export が適している場合

1ファイル1クラス、1ファイル1コンポーネントなど、モジュールが単一のメインエクスポートを持つ場合。

チームでの方針

プロジェクトによっては、どちらか一方に統一するルールを設けることもあります。

// Named Export のみを使うスタイル
// components/Button.js
export function Button(props) {
  // ...
}

// components/index.js
export { Button } from './Button.js';
export { Input } from './Input.js';

Named Export のみを使うと、インポート時の名前が一貫し、リファクタリングツールも効きやすくなります。一方、Default Export は React コンポーネントや Vue の単一ファイルコンポーネントでよく使われる慣習です。

どちらが正解というわけではなく、プロジェクトやチームの方針に従うのがベストです。