package.json の exports フィールド

package.json の exports フィールドは、パッケージのエントリーポイントを細かく制御できる機能です。Node.js 12.7 以降でサポートされ、モダンなパッケージ設計に欠かせません。

基本的な使い方

{
  "name": "my-package",
  "exports": {
    ".": "./dist/index.js",
    "./utils": "./dist/utils.js"
  }
}

これにより、以下のようにインポートできます。

import main from 'my-package';
import { helper } from 'my-package/utils';

main との違い

従来の main フィールドは単一のエントリーポイントしか定義できませんでした。

main

単一のエントリーポイントのみ。サブパスのエクスポートは制御できない。

exports

複数のエントリーポイント、条件付きエクスポート、サブパスの制限が可能。

条件付きエクスポート

環境やモジュールシステムに応じて、異なるファイルを提供できます。

{
  "name": "my-package",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "default": "./dist/index.js"
    }
  }
}
条件説明
importES Modules での読み込み時
requireCommonJS での読み込み時
defaultフォールバック
nodeNode.js 環境
browserブラウザ環境

サブパスのエクスポート

パッケージ内の特定のモジュールだけを公開できます。

{
  "name": "my-package",
  "exports": {
    ".": "./dist/index.js",
    "./components": "./dist/components/index.js",
    "./utils": "./dist/utils/index.js"
  }
}
import { Button } from 'my-package/components';
import { format } from 'my-package/utils';

パターンマッチング

ワイルドカードを使用して、複数のサブパスをまとめて定義できます。

{
  "name": "my-package",
  "exports": {
    ".": "./dist/index.js",
    "./components/*": "./dist/components/*.js",
    "./utils/*": "./dist/utils/*.js"
  }
}
import { Button } from 'my-package/components/Button';
import { formatDate } from 'my-package/utils/date';

内部モジュールの隠蔽

exports を定義すると、定義されていないサブパスへのアクセスは禁止されます。

{
  "name": "my-package",
  "exports": {
    ".": "./dist/index.js"
  }
}
// OK
import main from 'my-package';

// エラー(exports で定義されていない)
import internal from 'my-package/dist/internal.js';

複雑な設定例

{
  "name": "my-library",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    },
    "./utils": {
      "types": "./dist/utils.d.ts",
      "import": "./dist/utils.mjs",
      "require": "./dist/utils.cjs"
    },
    "./package.json": "./package.json"
  }
}
types 条件

TypeScript の型定義ファイルを指定。TypeScript 4.7+ でサポート。

package.json のエクスポート

package.json 自体へのアクセスを許可する場合に追加。

注意点

exports を定義すると、main フィールドより優先される
古い Node.js バージョンでは exports がサポートされていない
サブパスパターンは Node.js 14.13+ でサポート

フォールバック設定

古い環境との互換性のため、main と exports を併用することが推奨されます。

{
  "name": "my-package",
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  }
}

exports フィールドを適切に設定することで、パッケージの公開 API を明確にし、内部実装を隠蔽することができます。