投稿日:2024/11/24
更新日:2024/11/26
大規模なReactのアプリケーションを触るようになって、名前付きエクスポートとデフォルトエクスポート違い、メリット・デメリットについて考えるようになったのでまとめておきます。
ちなみに自分は圧倒的名前付きエクスポート派になります。
// エクスポート側
export default function sayHello() {
console.log("Hello!");
}
// インポート側
import hello from './sayHello'; // 好きな名前でインポート可能(sayHelloをhelloで呼び出せる)
hello(); // Hello!
export default
でエクスポートしたものは、インポート時に名前を変更できる。// エクスポート側
export const greet = () => console.log("Hi!");
export const farewell = () => console.log("Goodbye!");
// インポート側
import { greet, farewell } from './greetings';
greet(); // Hi!
farewell(); // Goodbye!
as
を使えば別名でインポート可能import { greet as sayHi } from './greetings';
sayHi(); // Hi!
ここからは名前付きエクスポートを推す理由について説明します。
名前付きエクスポートでは、エクスポートする関数やオブジェクトが明確に定義されているため、エディタでの補完機能が利用きます。また、VSコードの場合関数を command + クリック
で簡単に定義元にジャンプできるため、コードの追跡が容易です。
一方、デフォルトエクスポートでは、インポート側で名前を自由に付けられるため、補完が効きません。また、後者ではメソッドジャンプが利用できないため、コードの追跡時にまずインポート元のファイルを確認し、そこから目的のコードを探さなければならず、プロジェクト規模が大きくなるにつれて辛くなります。自分自身、長期間運用されているReactを触っていますが、デフォルトエクスポートのコードを追うのはかなり苦労します。
名前付きエクスポートを使用すると、モジュール内の個々の関数やオブジェクトを独立して扱うことができます。これにより、以下のメリットがあります
たとえば、デフォルトエクスポートではファイル全体の責任範囲が曖昧になりがちですが、名前付きエクスポートでは「この関数はこの責務を持つ」と明確に分離できます。これにより、コードの変更やレビューが効率的になります。
名前付きエクスポートは、ツリーシェイキングと呼ばれる最適化機能に対応しています。WebpackやRollupなどのバンドルツールを使用した際、未使用のエクスポートが自動的に削除され、結果的にバンドルサイズを削減できます。
一方で、デフォルトエクスポートはツリーシェイキングに適していない場合が多く、モジュール全体がインポートされてしまいます。その結果、使わないコードも含まれるため、バンドルサイズが無駄に大きくなるリスクがあります。
以下は例です:
// 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のみインポート
名前付きエクスポートの方が不要なコードを含まず、パフォーマンス面でも優れていると思います。
モジュールの設計思想としては、「モジュールは一つの主機能を提供するべき」という観点からデフォルトエクスポートの方がより思想に的した場合もあると思います。
しかし、実運用ではデフォルトエクスポートだと苦労する点が多いです。(特にコーディング規約が明確でない場合、大規模プロジェクトの場合など。)
デフォルトエクスポートは小規模なモジュールやシンプルなユーティリティでは適している場合もありますが、長期的な保守性を考慮するなら、名前付きエクスポートの方が上記の点で適していると思います。
いろんな記事があったので興味があれば読んでみると面白いかもです!