リポジトリ
ドキュメント
内部パッケージ

内部パッケージ

内部パッケージは、モノレポの内部でのみ使用されることを意図したパッケージです。クローズドソースのモノレポでアプリ間でコードを共有するのに非常に便利です。

内部パッケージは簡単に作成でき、最終的にnpmに公開したい場合は、外部パッケージに変えることができます。

パッケージを内部にする理由

外部パッケージは、パッケージレジストリに配置する前に、ファイルをバンドラーに通します。つまり、処理するために多くのツールが必要になります。

  • バンドラー:パッケージをビルドするため
  • バージョニング:バージョニングとリリースを支援するため
  • 公開:パッケージを公開するため

これらのファイルをローカルで使用する場合は、以下も必要になります

  • 開発スクリプト:ファイルが変更されたときにローカルでパッケージをバンドルするため

内部パッケージは公開されないため、これらの手順をすべてスキップできます。パッケージを自分でバンドルする代わりに、パッケージをインポートするアプリにバンドルさせます

これは複雑に聞こえるかもしれませんが、設定は非常に簡単です。

最初の内部パッケージ

モノレポ内に共有math-helpersパッケージを作成します。

1. モノレポを作成する

既存のモノレポがない場合は、ガイドを使用して作成してください。

2. 新しいパッケージを作成する

/packages内に、math-helpersという名前の新しいフォルダーを作成します。

mkdir packages/math-helpers

package.jsonを作成します

{
  "name": "math-helpers",
  "version": "0.0.1",
  "dependencies": {
    // Use whatever version of TypeScript you're using
    "typescript": "latest"
  }
}

srcフォルダーを作成し、packages/math-helpers/src/index.tsに TypeScript ファイルを追加します。

export const add = (a: number, b: number) => {
  return a + b;
};
 
export const subtract = (a: number, b: number) => {
  return a - b;
};

また、packages/math-helpers/tsconfig.jsontsconfig.jsonを追加する必要があります

{
  "compilerOptions": {
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "preserveWatchOutput": true,
    "skipLibCheck": true,
    "noEmit": true,
    "strict": true
  },
  "exclude": ["node_modules"]
}

素晴らしい!これで、内部パッケージに必要なファイルがすべて揃いました。

3. パッケージをインポートする

次に、パッケージをインポートして何が起こるかを確認します。アプリのいずれかに移動し、その package.json の依存関係にmath-helpersを追加します

{
  "dependencies": {
    "math-helpers": "*"
  }
}

ルートからすべてのパッケージをインストールして、依存関係が機能することを確認します。

次に、アプリのソースファイルの1つに、math-helpers からのインポートを追加します。

+ import { add } from "math-helpers";
 
+ add(1, 2);

おそらくエラーが表示されるでしょう!

Cannot find module 'math-helpers' or its corresponding type declarations.

それは、ステップを一つ飛ばしているからです。私たちは math-helpers/package.json に、パッケージのエントリーポイントが何かを伝えていません。

4. exports を修正する

packages/math-helpers/package.json に戻り、exports フィールドを追加します。

{
  "name": "math-helpers",
  "exports": {
    ".": "./src/index.ts"
  },
  "dependencies": {
    "typescript": "latest"
  }
}

これで、math-helpers モジュールをインポートするものはすべて、src/index.ts ファイルに直接ポイントされるようになります。それがインポートされるファイルです。

apps/web/pages/index.tsx に戻ります。エラーは消えているはずです!

5. アプリを実行してみる

次に、アプリの開発用スクリプトを実行してみましょう。デフォルトの turborepo では、これは以下のように簡単です。

turbo dev

起動すると、Webブラウザにエラーが表示されるでしょう。

../../packages/math-helpers/src/index.ts
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type,
currently no loaders are configured to process this file.
See https://webpack.dokyumento.jp/concepts#loaders

> export const add = (a: number, b: number) => {
|   return a + b;
| };

これは、バンドルされていないファイルを Next.js アプリにインポートしようとしたときに起こります。

解決策は簡単です。インポートする特定のパッケージのファイルをバンドルするように Next.js に指示する必要があります。

6. アプリの設定

next.config.jstranspilePackages を使用してそれを行うことができます (v13.1 以降が必要)。

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['math-helpers'],
};
 
module.exports = nextConfig;

開発用スクリプトを再起動し、ブラウザに移動します。

エラーは消えました!

7. まとめ

これで、math-helpers パッケージに任意の量のコードを追加し、モノレポ内の任意のアプリで使用できるようになりました。パッケージをビルドする必要さえありません。そのまま動作します。

このパターンは、チーム間で簡単に共有できるコードを作成するのに非常に強力です。

クイックリファレンス

クイックリファレンス - 新しい内部パッケージの作成

  1. packages/<folder> に新しいフォルダを作成します。
  2. package.json を追加し、nametypessrc/index.ts (または src/index.tsx) にポイントするようにします。
  3. 少なくとも1つの名前付きエクスポートを含む src/index.tsx を追加します。
  4. ルートからパッケージをインストールします。

クイックリファレンス - 内部パッケージのインポート

  1. 正しくインポートしているか確認します。
  2. アプリがそれをトランスパイルするように設定しているか確認します。