YASD-TECH
YASD TECH
# Next.js
# TypeScript

名前付きエクスポートとデフォルトエクスポートについて

投稿日:2024/11/24

更新日:2024/11/26

ttitleImage

前置き

大規模なReactのアプリケーションを触るようになって、名前付きエクスポートとデフォルトエクスポート違い、メリット・デメリットについて考えるようになったのでまとめておきます。

ちなみに自分は圧倒的名前付きエクスポート派になります。

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

  • 1つのモジュールで1つのエクスポートに限られる。
  • 名前はインポート時に自由に設定できる。
  • 主にモジュールの「主役」となる値や機能をエクスポートする際に使用。

書き方

App.ts
// エクスポート側
export default function sayHello() {
  console.log("Hello!");
}

// インポート側
import hello from './sayHello'; // 好きな名前でインポート可能(sayHelloをhelloで呼び出せる)
hello(); // Hello!

特徴

  • export default でエクスポートしたものは、インポート時に名前を変更できる。
  • 通常、ライブラリやユーティリティで、モジュール全体を代表する1つの値や関数をエクスポートするのに使われる。

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

  • 複数のエクスポートが可能
  • 名前を付けてエクスポートするため、インポート側でも同じ名前でインポートする必要がある
  • 主にモジュール内の複数の機能や値をエクスポートする際に使用

書き方

App.ts
// エクスポート側
export const greet = () => console.log("Hi!");
export const farewell = () => console.log("Goodbye!");

// インポート側
import { greet, farewell } from './greetings';
greet(); // Hi!
farewell(); // Goodbye!

特徴

  • 名前付きエクスポートは複数エクスポートできる
  • インポート時に必要な機能だけを選択してインポートできる
  • 名前を統一する必要があるが、as を使えば別名でインポート可能
App.ts
import { greet as sayHi } from './greetings';
sayHi(); // Hi!

名前付きエクスポートを推す理由

ここからは名前付きエクスポートを推す理由について説明します。

エディタとの互換性

名前付きエクスポートでは、エクスポートする関数やオブジェクトが明確に定義されているため、エディタでの補完機能が利用きます。また、VSコードの場合関数を command + クリック で簡単に定義元にジャンプできるため、コードの追跡が容易です。

一方、デフォルトエクスポートでは、インポート側で名前を自由に付けられるため、補完が効きません。また、後者ではメソッドジャンプが利用できないため、コードの追跡時にまずインポート元のファイルを確認し、そこから目的のコードを探さなければならず、プロジェクト規模が大きくなるにつれて辛くなります。自分自身、長期間運用されているReactを触っていますが、デフォルトエクスポートのコードを追うのはかなり苦労します。

より小さい単位での開発が可能

名前付きエクスポートを使用すると、モジュール内の個々の関数やオブジェクトを独立して扱うことができます。これにより、以下のメリットがあります

  • 変更が必要な場合、その関数やオブジェクトに限定して修正が可能
  • 他のエクスポートに影響を与えるリスクを最小限に抑えられる
  • チーム開発で並行作業がしやすくなる

たとえば、デフォルトエクスポートではファイル全体の責任範囲が曖昧になりがちですが、名前付きエクスポートでは「この関数はこの責務を持つ」と明確に分離できます。これにより、コードの変更やレビューが効率的になります。

バンドルサイズを下げられる

名前付きエクスポートは、ツリーシェイキングと呼ばれる最適化機能に対応しています。WebpackやRollupなどのバンドルツールを使用した際、未使用のエクスポートが自動的に削除され、結果的にバンドルサイズを削減できます。

一方で、デフォルトエクスポートはツリーシェイキングに適していない場合が多く、モジュール全体がインポートされてしまいます。その結果、使わないコードも含まれるため、バンドルサイズが無駄に大きくなるリスクがあります。

以下は例です:

App.ts
// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// デフォルトエクスポートの場合
export default {
  add,
  subtract,
};

// インポート例
import utils from './utils';
const result = utils.add(1, 2); // subtractも含まれる

// 名前付きエクスポートの場合
import { add } from './utils';
const result = add(1, 2); // addのみインポート

名前付きエクスポートの方が不要なコードを含まず、パフォーマンス面でも優れていると思います。

まとめ

モジュールの設計思想としては、「モジュールは一つの主機能を提供するべき」という観点からデフォルトエクスポートの方がより思想に的した場合もあると思います。

しかし、実運用ではデフォルトエクスポートだと苦労する点が多いです。(特にコーディング規約が明確でない場合、大規模プロジェクトの場合など。)

  1. エディタ補完が効くことで、開発体験を向上させることが可能
  2. コード変更の影響範囲を局所化できるため、保守性に長ける
  3. ツリーシェイキングによりバンドルサイズを最適化できる

デフォルトエクスポートは小規模なモジュールやシンプルなユーティリティでは適している場合もありますが、長期的な保守性を考慮するなら、名前付きエクスポートの方が上記の点で適していると思います。

いろんな記事があったので興味があれば読んでみると面白いかもです!

  • デフォルトエクスポート派

  • 名前付きエクスポート派

Index

  • 前置き
  • Default Export (デフォルトエクスポート)
  • 書き方
  • 特徴
  • 名前付きエクスポート (Named Export)
  • 書き方
  • 特徴
  • 名前付きエクスポートを推す理由
  • エディタとの互換性
  • より小さい単位での開発が可能
  • バンドルサイズを下げられる
  • まとめ