Named ExportとDefault Exportの理解

🌐

この記事は DeepL によって翻訳されました。誤訳があれば教えてください!

Named Export

Named Exportはモジュールから複数の変数、関数、クラスをエクスポートするときに使います。エクスポートされた各要素は名前を持ち、選択的に必要な部分だけをインポートすることができます。

例えば、次のようにコードを書きます。

// utils.js
export const PI = 3.14export function add(a, b) {
  return a + b;
}

export class Calculator {
  subtract(a, b) { {
    return a - b;
  }
}

上のようにexportをしたら、使うところでは下記のようにimportすることができます。

// main.js
import { PI, add, Calculator } from './utils.js'console.log(PI); // 3.14
console.log(add(2, 3)); // 5

const calc = new Calculator();
console.log(calc.subtract(5, 2)); // 3

Default Export

Default Exportは、モジュールから一つのデフォルト値をエクスポートするために使用します。一つのモジュール当たり一つのDefault Exportだけを持つことができ、インポートする時、名前を指定することができます。

下記のようにexportします、

// logger.js
export default function log(message) {
  console.log(message);
}

次のようにimportします。

// app.js
import log from './logger.js'log('こんにちは!'); // こんにちは!

主な違い

  1. exportの数

    • Named Export: 複数可能
    • Default Export: モジュールごとに一つだけ可能
  2. import文法

    • Named Export:import { name1, name2 } from './module';
    • Default Export:import anyName from './module';
  3. 名前の変更

    • Named Export:import { originalName as newName } from './module';
    • Default Export: インポート時に自由に名前指定可能
  4. 全体インポート

    • Named Export:import * as moduleName from './module';
    • Default Export: 既に一つのオブジェクトとして扱われるので、完全なインポートは不要です。
  5. 動的インポート

    • Named Export:import('./module').then(module => module.namedExport)
    • Default Export:import('./module').then(module => module.default)

いつ何を使うべきか?

  • Named Export: モジュールで色んなユーティリティ関数や変数をエクスポートして、これを選択的にインポートして使いたい時便利です。
  • Default Export: モジュールの主な機能やクラスをエクスポートする時使います。

index.js活用

下記のようにフォルダ構造を持ってるプロジェクトを見てみましょう。

Image.png

各コンポーネントは下記のようにNamed Exportされています。

const TestComponent = () => { { return
  return <div></div>;
};

export { TestComponent };

これを書くためには次のようにimportする必要があります。

import { TestComponent } from '@/components/ui/TestComponent.tsx'import { TestComponent2 } from '@/components/ui/TestComponent2.tsx'function App() {
  return (
    <div><TestComponent /><TestComponent2 /> </div
    </div> </div
  )です;
}

デフォルトのAppをエクスポートします;

下記のようにindex.js(ts)ファイルを作って再exportしてみましょう。

// Named Export
export { TestComponent } from './TestComponent'export { TestComponent2 } from './TestComponent2'// デフォルトのエクスポート
export { default as TestComponent } from './TestComponent'; // Default export { default as TestComponent } from './TestComponent'; // Default Export;
export { default as TestComponent2 } from './TestComponent2'

そしたらimportするところでは下記のようにもっときれいにimportすることができます。

import { TestComponent, TestComponent2 } from '@/components/ui';

function App() {
  return (
    <div>
      <TestComponent />
      <TestComponent2 />
    </div>
  );
}

export default App;

index.jsを使う時の長所と短所

長所

  • ディレクトリの入口の役割をしてモジュール構造を簡単に作ることができます。
  • 複数のファイルの内容を一つにまとめてエクスポートすることができ、import文を簡潔にすることができます。
  • ディレクトリ構造を変更しても外部コードに影響を与えない。

短所

  • あまりにも多くの内容をindex.jsに集めると、ファイルが複雑になる可能性があります。

Avoid Export Default

この記事ではExport Defaultを使うことを避けるように言っています。(少なくともTypeScriptプロジェクトでは?)主な理由は下記の通りです。

名前変更がサポートされない

IDEでリファクタリング機能で名前を変更する時、IDEは自動的に名前を変更してくれません。例えば、TestComponentの名前をTestComponent2に変えても、importする部分では変更されません。しかし、Named Exportを使う場合はうまく変更してくれます。

名前変更の自由度による一貫性の欠如

  • default exportを使うとインポートする時、任意の名前を使うことができるので、同じモジュールを別のファイルで別の名前で使うことができます。
  • これはコードの一貫性を損ない、混乱を引き起こす可能性があります。

タイプ情報の欠如

  • default export は型情報を提供しないので、どのような型のオブジェクトや関数がエクスポートされるのかが明確でない場合があります。