Closed12

途中からTurborepoを導入する

FractFract

現在Next.jsのApp下にclientとadminのページが存在しているので分けて開発したい
モノレポの知識もないので合わせて勉強する。

FractFract

モノレポはプロジェクトを単一のリポジトリで合わせて開発する手法らしい
現在もバックとフロントを同一のリポジトリで開発しているためモノレポといえる?

今回はフロント内のNext.jsをさらに分割する。
フロンエンドではプロジェクト間で同一のライブラリや共通して使用できるコンポーネントなどを管理したい。そういった際に使用できるのがTurborepo?Turborepo以外のツールは聞いたことがない()

turborepoは依存関係の自動解決・ビルドキャッシュと並列化を用いてモノレポの問題点である複雑性とビルド時間の増加に対応している

FractFract

現在のプロジェクトにTurborepoを導入する。
現在のリポジトリではnpmを使用しているがturborepoのインストールセクションでpnpmがデフォルトだったのでpnpmにも移行する(他のライブラリやフレームワークのインストールセクションでもpnpmがデフォルトで選択されていたのでそういう流れ?)

FractFract

現在の存在するフロント側のディレクトリ名をリネームし同一の名前でturborepoのプロジェクトを作成し以前のコードを移植する計画.

pnpm dlx create-turbo@latest
上記を実行しプロジェクトを作成すると下記のようなものが自動生成される。

apps:プロジェクト
packages:共通するUIや設定
root:全体で使用するコンフィグなど
を配置する感じですね。

.
├── .turbo
│   ├── cache
│   │   ├── 0bbe7ff07823011d-meta.json
│   │   ├── 0bbe7ff07823011d.tar.zst
│   │   ├── 5606935383f1019b-meta.json
│   │   └── 5606935383f1019b.tar.zst
│   ├── cookies
│   │   ├── 1.cookie
│   │   ├── 2.cookie
│   │   ├── 3.cookie
│   │   ├── 4.cookie
│   │   └── 5.cookie
│   ├── daemon
│   │   └── 3edd7b37ebe95808-turbo.log.2025-08-12
│   └── preferences
│       └── tui.json
├── .vscode
│   └── settings.json
├── apps
│   ├── docs
│   │   ├── .turbo
│   │   │   └── turbo-build.log
│   │   ├── app
│   │   │   ├── fonts
│   │   │   │   ├── GeistMonoVF.woff
│   │   │   │   └── GeistVF.woff
│   │   │   ├── favicon.ico
│   │   │   ├── globals.css
│   │   │   ├── layout.tsx
│   │   │   ├── page.module.css
│   │   │   └── page.tsx
│   │   ├── public
│   │   │   ├── file-text.svg
│   │   │   ├── globe.svg
│   │   │   ├── next.svg
│   │   │   ├── turborepo-dark.svg
│   │   │   ├── turborepo-light.svg
│   │   │   ├── vercel.svg
│   │   │   └── window.svg
│   │   ├── .gitignore
│   │   ├── eslint.config.js
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── README.md
│   │   └── tsconfig.json
│   └── web
│       ├── .turbo
│       │   └── turbo-build.log
│       ├── app
│       │   ├── fonts
│       │   │   ├── GeistMonoVF.woff
│       │   │   └── GeistVF.woff
│       │   ├── favicon.ico
│       │   ├── globals.css
│       │   ├── layout.tsx
│       │   ├── page.module.css
│       │   └── page.tsx
│       ├── public
│       │   ├── file-text.svg
│       │   ├── globe.svg
│       │   ├── next.svg
│       │   ├── turborepo-dark.svg
│       │   ├── turborepo-light.svg
│       │   ├── vercel.svg
│       │   └── window.svg
│       ├── .gitignore
│       ├── eslint.config.js
│       ├── next-env.d.ts
│       ├── next.config.js
│       ├── package.json
│       ├── README.md
│       └── tsconfig.json
├── packages
│   ├── eslint-config
│   │   ├── base.js
│   │   ├── next.js
│   │   ├── package.json
│   │   ├── react-internal.js
│   │   └── README.md
│   ├── typescript-config
│   │   ├── base.json
│   │   ├── nextjs.json
│   │   ├── package.json
│   │   └── react-library.json
│   └── ui
│       ├── src
│       │   ├── button.tsx
│       │   ├── card.tsx
│       │   └── code.tsx
│       ├── eslint.config.mjs
│       ├── package.json
│       └── tsconfig.json
├── .gitignore
├── .npmrc
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── README.md
└── turbo.json

23 directories, 78 files

FractFract

turborepo用の設定を記述する。(長いのでtrと略す)
trではWorkspace単位で管理を行う。今回生成されたapps/web,apps/docs,packages/ui ...などがワークスペースらしい。
各Workspaceのpackage.jsonのnameがワークスペース名となる。
合わせてnode packageを追加するときと同じ感じに他のワークスペースへの依存関係を記述する。trはこの記述を読み取りビルドの依存関係を解決する
この記述方法はpnpmでの記述方法らしいnpm workspaceでの書き方と異なる

{
 // ワークスペース名
  "name": "web",
}
....
  "dependencies": {
 // 共通UIへの依存
    "@repo/ui": "workspace:*",
    "next": "^15.4.2",
    "react": "^19.1.0",
    "react-dom": "^19.1.0"
  },
  "devDependencies": {
 // コンフィグへの依存
    "@repo/eslint-config": "workspace:*",
    "@repo/typescript-config": "workspace:*",
    "@types/node": "^22.15.3",
    "@types/react": "19.1.0",
    "@types/react-dom": "19.1.1",
    "eslint": "^9.31.0",
    "typescript": "5.8.2"
  }

FractFract

調べてみた感じpnpm dlx shadcn@canary initでshadcn用のプロジェクトを作成した方がパスなどの設定をショートカットできそう。
前回作成したプロジェクトを消して前述のコマンドで再作成する。

再作成したプロジェクトではapps/docsは生成されない.
packages/uiにtailwindcss・shadcnコンポーネント・global.cssが置かれWorkspaceからエクスポートされている。

FractFract

現在のプロジェクトを移行するために新規Next.jsプロジェクトをappsに追加する
appsにnext.jsをpnpmで追加します。※全てデフォルト設定
pnpm create next-app apps/admin -- --typescript
次にtr用の設定を追加します。
こちらはpnpm dlx shadcn@canary initで生成されたweb ワークスペースを参考にします

adminワークスペースが起動するポートをwebワークスペースと変更し起動するか確認します。( "dev": "next dev --turbopack --port 5000")

FractFract

起動したのでpackage.jsonに依存関係を追加してコンポーネントをインポートできるようにする。

  "dependencies": {
    "@workspace/ui": "workspace:*",
  },
  "devDependencies": {
    "@workspace/typescript-config": "workspace:*",
  }
FractFract

pnpm install するとWorkspaceを依存関係として認識してくれる。
installしないとimport出来なかった。

FractFract

自作していたサイドバーなどを新規に作成したAdmin Workspaceに移植してインポートを書き換えた。
CSSが当たっていなかったため。
以下を設定

// postcss.config.mjs
export { default } from "@workspace/ui/postcss.config";
// page.tsx
import "@workspace/ui/globals.css";

表示も問題なさそうなので同一の手順でclient側も移植する

FractFract

どのワークスペースでも必要になりうるものはrootでpnpm add に -wをオプションをつけてインストールする。

このスクラップは1ヶ月前にクローズされました