目的
デフォルトエクスポートと名前付きエクスポートの違いがわからなかったのでまとめる。
結論
- デフォルトエクスポート: ファイル内で1つの主要な機能を提供する場合
- 名前付きエクスポート: ファイル内で複数の関連する機能を提供する場合
そもそもモジュールのエクスポートってなんだ?
モジュールのエクスポートとは、あるファイル内で定義された関数、クラス、変数、またはコンポーネントを他のファイルから利用できるようにするJavaScript
やTypeScript
の仕組みのこと。
デフォルトエクスポート
-
{}
なしで呼び出す - 任意の名前で
import
できる(Pagination
の部分はMyPagination
でも可)- 名前を自由に変更できるがゆえ、チーム開発では一貫性を保つのが難しい場合も(同じモジュールを指しているのに名前が異なると、コードの可読性が低下する)
importしてモジュールを使う側
import Pagination from '@/app/ui/invoices/pagination';
- 1ファイルからは1つのエクスポート(以下の例で言うと
Pagination
)だけが可能
モジュールとして提供する側
// app/ui/invoices/pagination.tsx
export default function Pagination({ totalPages }: { totalPages: number }) {
return <div>Pagination Component with {totalPages} pages</div>;
}
名前付きエクスポート
-
{}
つきで呼び出す
importしてモジュールを使う側
import { CreateInvoice } from '@/app/ui/invoices/buttons';
- 名前付きエクスポートは、インポート時にエクスポート名を明示するため、どの機能がどのファイルから来ているのかが分かりやすい(コードの追跡やリファクタリング時には優位)
- 1ファイルから複数のエクスポート(以下の例でいうと
CreateInvoice
とDeleteInvoice
)が可能
モジュールとして提供する側
// app/ui/invoices/buttons.tsx
export const CreateInvoice = () => {
return <button>Create Invoice</button>;
};
export const DeleteInvoice = () => {
return <button>Delete Invoice</button>;
};
名前付きエクスポートだとこんなメリットもある
- 名前付きエクスポートは、静的解析ツール(
ESLint
やTypeScript
)で追跡しやすく、リファクタリング時に安全性が高い
// 名前付きエクスポートのリファクタリング例
export const CreateInvoice = () => { ... };
export const DeleteInvoice = () => { ... };
// 名前を変更した場合、importしてモジュールを使う側も変更するよう検出してくれる
export const AddInvoice = () => { ... }; // CreateInvoice → AddInvoice に変更
思ったこと
「1ファイル1目的」のモジュールにした方が良い設計になりそうだが、
関連性が高い機能をまとめることで管理が楽になる場合もある。
「1ファイル1目的」の原則を守るべきか、関連性が高い機能をまとめるべきか、プロジェクトの規模やチームのコーディング規約に応じて、あらかじめ決めおくのがよさそう。