React + Express を活用したモノレポ環境構築ガイド:Turborepoで効率的な開発を実現

  • react
    react
  • expressjs
    expressjs
  • typescript
    typescript
2025/02/05に公開

はじめに

本記事では、React、Express、GraphQL、Turborepoを使って、モノレポ環境を構築し、効率的な開発環境を整える方法について解説します。モノレポ構成の利点を活かし、複数のプロジェクトを1つのリポジトリで管理することで、依存関係の管理やビルド時間の短縮、開発のスピードアップが可能になります。Turborepoを活用しフロントエンドとバックエンドを効率的に開発できるセットアップを一緒に学んでいきましょう。

今回のゴール

フロントエンドであるReactとバックエンドであるExpressを1つのリポジトリにセットアップし、turborepoを使ってまとめて起動できるようにします。

Image from Gyazo

その後、ReactからExpressにアクセスできることを確認します。

Image from Gyazo

ディレクトリ構成が初見では複雑に見えますので詳しい解説も載せています。

.
├── apps
│   ├── backend
│   │   ├── src
│   │   │   └── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── frontend
│       ├── dist
│       │   ├── assets
│       │   │   ├── index-D5Y6grW-.js
│       │   │   └── index-kQJbKSsj.css
│       │   ├── index.html
│       │   └── vite.svg
│       ├── public
│       │   └── vite.svg
│       ├── src
│       │   ├── assets
│       │   │   └── react.svg
│       │   ├── App.tsx
│       │   ├── main.tsx
│       │   └── vite-env.d.ts
│       ├── .gitignore
│       ├── README.md
│       ├── eslint.config.js
│       ├── index.html
│       ├── package.json
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       ├── tsconfig.node.json
│       └── vite.config.ts
├── package-lock.json
├── package.json
└── turbo.json

Turborepoとは

Turborepo(ターボレポ)は、モノレポ(monorepo)構成を管理するためのツールで、主にJavaScriptやTypeScriptのプロジェクトに利用されます。モノレポとは、複数のプロジェクトやパッケージを一つのリポジトリ内で管理するアプローチです。Turborepoは、このようなモノレポを効率的に扱うためのツールです。

Turborepoの主な特徴

  • ビルドパイプラインの高速化: Turborepoは、依存関係の管理を効率化するため、インクリメンタルビルドをサポートします。変更された部分のみを再ビルドすることで、ビルド時間を短縮し、開発を加速します。

  • キャッシュ機能: ビルド結果をキャッシュすることで、同じ処理を何度も行わずに済みます。これにより、CI/CDやローカル開発環境でのビルドが高速化されます。

  • 依存関係の管理: モノレポ内の複数のパッケージ間での依存関係を効率よく管理できます。Turborepoは、タスクやスクリプトが依存するパッケージ間で自動的に適切な順序で処理を実行します。

  • 分散型タスク実行: 複数のパッケージが存在する場合でも、Turborepoは並列にタスクを実行して、開発のスピードを向上させます。

  • 簡単な設定: Turborepoは、turbo.jsonという設定ファイルを用いてプロジェクトの設定を簡単に管理できます。また、npmやpnpm、yarnなどのパッケージマネージャーと統合されており、標準的なツールチェインと共に動作します。

  • CI/CDサポート: Turborepoは、CI/CDパイプラインを効率的に設定できるようサポートします。変更のあった部分だけをビルドし、無駄な作業を省けます。

セットアップ

まずは全体のプロジェクトのセットアップから始めます。

mkdir Documents/workspace/react-express-graphql-turborepo
cd Documents/workspace/react-express-graphql-turborepo
npm init -y

Turborepoを使えるようインストールします。

npm install turbo -D

次にTurborepoの設定を行います。
タスクという形でビルドや開発モードでの起動などの設定ができます。

turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

devで起動する時は基本的に長時間実行されるもので"persistent": true を入れることでreactexpressの双方が他タスクに影響を与えて中断されないようにしています。

次にルート直下のpackage.jsonの修正をします。

package.json
{
  "name": "react-express-graphql-turborepo",
+ "workspaces": ["apps/*", "packages/*"],
  "version": "1.0.0",
  "description": "",
- "main": "index.js",
+ "packageManager": "npm@10.9.2",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "turbo": "^2.4.0"
  }
}

package.jsonのworkspacesは、モノレポ(monorepo)を構築するための設定です。モノレポとは、複数のパッケージやアプリケーションを単一のリポジトリ内で管理するアプローチです。

workspacesを使用すると、異なるパッケージ(アプリケーションやライブラリ)を同じリポジトリ内で効率的に管理でき、依存関係の共有やインストールの高速化、開発の効率化ができます。

以上でルート直下での初期設定は終了となります。

フロントエンド(React + Vite)の作成

ここから個別のアプリケーションの設定となります。
まずはフロントエンドから設定してきます。

mkdir apps
cd apps
npm create vite@latest frontend
apps/frontend/package.json
{
-  "name": "frontend",
+  "name": "@react-express-graphql-turborepo/frontend",
  "private": true,

スコープ付きパッケージの設定をします。
今回の記事ではまだあまり重要ではありませんが一旦設定しておきます。

ViteとReactの必要なファイルをダウンロードできたのでパッケージをインストールします。

cd apps/frontend
npm install

インストールが終わったら念のため起動し動作確認をしておきます。

npm run dev

下記のように表示され、http://localhost:5173/にアクセスできればOKです。

 VITE v6.1.0  ready in 319 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

以上でVite + Reactによるフロントエンドの設定は終了です。

今回はモノレポ構成についてがメインとなるためViteやReactについての記載は最小限にしていますが、これらのツールについて詳しく知りたい方はこちらの記事もご参考ください。

https://shinagawa-web.com/blogs/react-vite-setup-guide-for-fast-development

バックエンド(Experss)の作成

次にバックエンドとしてExpressの設定を行います。

まずはパッケージのインストールを行います。

mkdir apps/backend && cd apps/backend
npm init -y
npm i express cors dotenv
npm i -D  typescript ts-node @types/node @types/express @types/cors

その後、スコープ付きパッケージの設定、tsconfig.jsonの設定を行います。

apps/backend/package.json
{
- "name": "backend",
+ "name": "@react-express-graphql-turborepo/backend",
  "version": "1.0.0",
tsconfig.json
{
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "module": "CommonJS",
    "target": "ES6",
    "esModuleInterop": true
  }
}

Expressを動かせる環境ができましたら実際に起動するファイルを作成します。

apps/backend/src/index.ts
import express from "express";
import cors from "cors";

const app = express();
const PORT = process.env.PORT || 4000;

app.use(cors());
app.use(express.json());

app.get("/", (req, res) => {
  res.send("Hello from Express!");
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

まずはhttps://localhost:4000でアクセスすると、Hello from Express!と返ってくるようにしました。

ファイルが作成できましたら、package.jsonで起動する処理を定義します。

package.json
- "main": "index.js",
+ "main": "index.ts",
  "scripts": {
+   "dev": "ts-node src/index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

念のためExpressが起動できるか確認します。

npm run dev
Server is running on http://localhost:4000

起動できましたら、curlでレスポンスを確認します。

curl http://localhost:4000
Hello from Express!

以上でExperssのセットアップは終了となります。

こちらについてもExpressの記載は最小限にしていますが、詳しく知りたい方はこちらの記事もご参考ください。

https://shinagawa-web.com/blogs/express-typescript-setup-guide

フロントエンドからバックエンドにアクセス

fetchモジュールを使って先ほど返ってきたHello from Express!をブラウザで表示させます。

apps/frontend/src/App.tsx
import { useEffect, useState } from "react";

function App() {
  const [message, setMessage] = useState("");

  useEffect(() => {
    fetch("http://localhost:4000")
      .then((res) => res.text())
      .then((data) => setMessage(data));
  }, []);

  return (
    <div>
      <h1>React + Express</h1>
      <p>API Response: {message}</p>
    </div>
  );
}

export default App;

初期設定のCSSが残って影響を与えるので一旦削除します。

rm apps/frontend/src/index.css
rm apps/frontend/src/App.css

またcssを読み込んでいるファイルも修正しておきます。

apps/frontend/src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
- import './index.css'
import App from './App.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

一通り設定ができましたのでReactとExpressをTurborepoから起動します。
ルート直下で下記コマンドを実行します。

npm run dev

起動でき、APIのレスポンスがブラウザに表示されることを確認します。

Image from Gyazo

Image from Gyazo

ディレクトリ構成について

基本的にはapps配下がメインとなります。
今回はfrontend, backendという2つのディレクトリを用意してそれぞれ管理する形としました。

tree -I node_modules -I .git -I .turbo --dirsfirst -a
.
├── apps
│   ├── backend
│   │   ├── src
│   │   │   └── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── frontend
│       ├── dist
│       │   ├── assets
│       │   │   ├── index-D5Y6grW-.js
│       │   │   └── index-kQJbKSsj.css
│       │   ├── index.html
│       │   └── vite.svg
│       ├── public
│       │   └── vite.svg
│       ├── src
│       │   ├── assets
│       │   │   └── react.svg
│       │   ├── App.tsx
│       │   ├── main.tsx
│       │   └── vite-env.d.ts
│       ├── .gitignore
│       ├── README.md
│       ├── eslint.config.js
│       ├── index.html
│       ├── package.json
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       ├── tsconfig.node.json
│       └── vite.config.ts
├── package-lock.json
├── package.json
└── turbo.json

トップレベルのディレクトリ

.
├── package-lock.json
├── package.json
├── turbo.json
  1. package.json
    • モノレポ全体のルート package.json
    • apps/backend や apps/frontend の依存関係を統合管理する
    • workspace の設定
  2. package-lock.json
    • インストールされた依存関係のバージョンが固定されるファイル
    • npm install を実行すると自動生成される
  3. turbo.json
    • Turborepo の設定ファイル
    • どのパッケージを apps に含めるか、どのスクリプトを並列/キャッシュ実行するかを定義

アプリケーションのディレクトリ (apps/)

├── apps
│   ├── backend
│   └── frontend
  • apps/ 内に backend (Express) と frontend (React + Vite) が分かれている
  • モノレポの標準的なディレクトリ構造
  • backendfrontend をそれぞれ 独立したプロジェクトとして管理

バックエンド (apps/backend/)

│   ├── backend
│   │   ├── src
│   │   │   └── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
  1. src/index.ts
    • Express のエントリーポイント
    • サーバーを起動するメインファイル
  2. package.json
    • バックエンドの 依存関係やスクリプト を管理

フロントエンド (apps/frontend/)

│   └── frontend
│       ├── dist
│       │   ├── assets
│       │   │   ├── index-D5Y6grW-.js
│       │   │   └── index-kQJbKSsj.css
│       │   ├── index.html
│       │   └── vite.svg
│       ├── public
│       │   └── vite.svg
│       ├── src
│       │   ├── assets
│       │   │   └── react.svg
│       │   ├── App.tsx
│       │   ├── main.tsx
│       │   └── vite-env.d.ts
│       ├── .gitignore
│       ├── README.md
│       ├── eslint.config.js
│       ├── index.html
│       ├── package.json
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       ├── tsconfig.node.json
│       └── vite.config.ts
  1. dist/
    • Vite でビルドされたファイルが格納される
    • assets/ に JS, CSS, 画像などのビルド成果物 が入る
  2. public/
    • 静的ファイル を格納
    • vite.svg は Vite のデフォルトアイコン
    • public/ のファイルは dist/ にコピーされる
  3. src/
    • フロントエンドのソースコード
  4. vite.config.ts
    • Vite の設定ファイル
    • React プラグインや alias 設定を記述

さいごに

この記事を通じて、Turborepoを使用したモノレポ構成の基本的なセットアップ方法と、React + ViteのフロントエンドとExpressのバックエンドを統合する方法を学んでいただけたことと思います。このような構成により、複数のアプリケーションを効率よく管理し、ビルドの高速化や依存関係の管理が簡単に行えるようになります。これからモノレポを使った開発環境を整備する際の参考にしていただければ幸いです。Turborepoを使うことで、開発の生産性を大幅に向上させることができますので、ぜひ実際のプロジェクトに取り入れてみてください。

Xでシェア
Facebookでシェア
LinkedInでシェア

記事に関するお問い合わせ📝

記事の内容に関するご質問、ご意見などは、下記よりお気軽にお問い合わせください。
ご質問フォームへ

技術支援などお仕事に関するお問い合わせ📄

技術支援やお仕事のご依頼に関するお問い合わせは、下記よりお気軽にお問い合わせください。
お問い合わせフォームへ

関連する技術ブログ

弊社の技術支援サービス

お問い合わせ

経営と現場をつなぐ“共創型”の技術支援。
成果に直結するチーム・技術・プロセスを共に整えます。

お問い合わせ