🐥

Turborepoで内部パッケージを利用

2023/09/16に公開

はじめに

Turborepo で Internal Package(内部パッケージ)の利用について解説します。Internal Package(内部パッケージ)とは、モノリポジトリ内でのみ使用されることを目的としたパッケージです。

この記事では、以下の記事を参考に Turborepo のプロジェクトを新規に作成し、Internal Package を作成し、アプリケーションで利用します。

https://turbo.build/repo/docs/handbook/sharing-code/internal-packages

作業コードは以下です。

https://github.com/hayato94087/turborepo-nextjs-package-sample

Turborepo で作業環境を作成

create-turbo で、新規に Turborepo プロジェクトを作成します。

$ pnpm dlx create-turbo@latest

>>> TURBOREPO

>>> Welcome to Turborepo! Let's get you set up with a new codebase.

? Where would you like to create your turborepo? turborepo-nextjs-package-sample
? Which package manager do you want to use? pnpm

Downloading files. This might take a moment.

>>> Created a new Turborepo with the following:

apps
 - apps/docs
 - apps/web
packages
 - packages/eslint-config-custom
 - packages/tsconfig
 - packages/ui

Installing packages. This might take a couple of minutes.

>>> Success! Created a new Turborepo at "turborepo-nextjs-package-sample".
Inside that directory, you can run several commands:

  pnpm run build
     Build all apps and packages

  pnpm run dev
     Develop all apps and packages

  pnpm run lint
     Lint all apps and packages

Turborepo will cache locally by default. For an additional
speed boost, enable Remote Caching with Vercel by
entering the following command:

  pnpm dlx turbo login

We suggest that you begin by typing:

  cd turborepo-nextjs-package-sample
  pnpm dlx turbo login

プロジェクトディレクトリーに移動します。

$ cd turborepo-nextjs-package-sample

web アプリケーションの page.tsx を以下で上書きし、サンプルのページを作成します。

apps/web/app/page.tsx
export default function Page(): JSX.Element {
  return (
    <h1 className="text-xl">Web</h1>
  );
}

ローカルで実行します。

$ pnpm dev --filter=web

Alt text

コミットします。

$ pnpm build
$ git add .
$ git commit -m "Turborepoの初期環境を構築"

Internal Package を作成

それでは、math-hekpers という名前の Internal Package を作成します。

$ mkdir packages/math-helpers

package.json を作成します。

$ touch packages/math-helpers/package.json
packages/math-helpers/package.json
{
  "name": "math-helpers",
  "main": "src/index.ts",
  "types": "src/index.ts",
  "dependencies": {
    "typescript": "latest"
  }
}

src フォルダーを作成し、packages/math-helpers/src/index.ts にて実装します。

$ mkdir -p packages/math-helpers/src
$ touch packages/math-helpers/src/index.ts
packages/math-helpers/src/index.ts
export const add = (a: number, b: number) => {
  return a + b;
};

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

TypeScript を利用しているので、tsconfig.js を追加します。

$ touch packages/math-helpers/tsconfig.json
packages/math-helpers/tsconfig.json
{
  "compilerOptions": {
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "moduleResolution": "node",
    "preserveWatchOutput": true,
    "skipLibCheck": true,
    "noEmit": true,
    "strict": true
  },
  "exclude": ["node_modules"]
}

コミットします。

$ pnpm build
$ git add .
$ git commit -m "math-helpersを作成"

これで Internal Package は作成完了しました。

Internal Package を利用

web アプリケーションから math-helpers を利用できるように設定します。

math-helpers のパッケージを package.json に追加します。

apps/web/package.json
{
  "name": "web",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
+   "math-helpers": "workspace:*",
    "next": "^13.4.19",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "ui": "workspace:*"
  },
  "devDependencies": {
    "@next/eslint-plugin-next": "^13.4.19",
    "@types/node": "^17.0.12",
    "@types/react": "^18.0.22",
    "@types/react-dom": "^18.0.7",
    "eslint-config-custom": "workspace:*",
    "tsconfig": "workspace:*",
    "typescript": "^4.5.3"
  }
}

next.config.js の設定で、transpilePackagesmath-helpers を追加します。

apps/web/next.config.js
-module.exports = {
-  reactStrictMode: true,
-  transpilePackages: ["ui"],
-};
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+  reactStrictMode: true,
+  transpilePackages: ["ui", "math-helpers"],
+};
+
+module.exports = nextConfig;

補足、上記実施しない場合のエラー

上記を実施しないと以下のようなエラーが出ます。

../../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.js.org/concepts#loaders
> export const add = (a: number, b: number) => {
|   return a + b;
| };

webアプリケーションのパッケージをインストールします。

$ pnpm i

math-helpersをソースに追加します。

apps/web/app/page.tsx
+import { add } from "math-helpers";

export default function Page(): JSX.Element {
  return (
+   <>
      <h1 className="text-xl">Web</h1>
+     <p>1 + 2 = {add(1, 2)}</p>
+   </>
  );
 }

以下のようにエラーが表示されている場合は、TS Server / ESLint Server を再起動します。

Alt text

Alt text

ローカルで実行します。

$ pnpm dev --filter=web

Alt text

コミットします。

$ pnpm build
$ git add .
$ git commit -m "Internal Packageが利用できるように設定"

次のステップ

Internal Packageだとバージョン管理が難しいので、External Packageとして切り出すことを検討したいと思います。

まとめ

  • Turborepo で Internal Packageの利用について解説しました。

  • 作業コードは以下です。

https://github.com/hayato94087/turborepo-nextjs-package-sample

参考

https://turbo.build/repo/docs/handbook/sharing-code/internal-packages

Discussion