Open10

Turborepo

hayato94087hayato94087

Turbo - 1プロジェクトでの利用

はじめに

以下の公式ページに記載の内容でTurborepoをNext.jsで試してみました。

https://turbo.build/repo/docs/getting-started/add-to-project

Turboのインストール

Turboをグローバルにインストール

terminal
yarn global add turbo

作業環境に移動

terminal
cd /Users/hayato94087/Private/turborepo

Next.jsをインストール

Next.jsを作成

terminal
yarn create next-app nextjs-turbo-1 --typescript --eslint --src-dir --import-alias "@/*"
cd nextjs-turbo-1
yarn

実行環境を設定

turbo.jsonを作成します。

turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "outputs": [".next/**"]
    },
    "lint": {}
  }
}

.gitignoreを修正し、.turboを無視するよう設定します。

.gitignore
+ # turbo
+ .turbo

Turboを実行

buildlintturboで実行します。buildlintが同時に実行されます。

terminal
turbo build lint
実行結果
Tasks:    2 successful, 2 total
Cached:    0 cached, 2 total
  Time:    7.13s 

開発環境をturboで実行させます。

terminal
turbo dev
実行結果
• Running dev
• Remote caching disabled
dev: cache bypass, force executing 5763bc06079d2782
dev: yarn run v1.22.19
dev: warning ../../../package.json: No license field
dev: $ next dev
dev: ready - started server on 0.0.0.0:3000, url: http://localhost:3000
warning ../../../package.json: No license field
dev: event - compiled client and server successfully in 1517 ms (170 modules)

まとめ

turborepoを利用する方法を記載しました。

以下が作業結果のリポジトリ

https://github.com/hayato94087/nextjs-turbo-1

hayato94087hayato94087

複数プロジェクトが入っているサンプルの実行

はじめに

Turborepoの公式サイトで提供されているbasicのexampleをローカルで構築する。
このbasicには複数のシンプルなNext.jsのプロジェクトが入っています。

https://github.com/vercel/turbo/tree/main/examples/basic

インストール

リポジトリをローカルに作成

terminal
npx degit vercel/turbo/examples/basic basic
cd basic

パッケージをインストール

terminal
pnpm i 
terminal
Scope: all 6 workspace projects
Lockfile is up to date, resolution step is skipped
Packages: +278
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/hayato94087/Library/pnpm/store/v3
  Virtual store is at:             node_modules/.pnpm
Downloading registry.npmjs.org/turbo-darwin-64/1.6.3: 6.49 MB/6.49 MB, done
Downloading registry.npmjs.org/next/13.1.1: 8.51 MB/8.51 MB, done
Downloading registry.npmjs.org/typescript/4.9.3: 11.6 MB/11.6 MB, done
Downloading registry.npmjs.org/@next/swc-darwin-x64/13.1.1: 25.9 MB/25.9 MB, done
Progress: resolved 278, reused 215, downloaded 63, added 278, done
node_modules/.pnpm/core-js-pure@3.26.1/node_modules/core-js-pure: Running postinstall script, done in 85ms
node_modules/.pnpm/turbo@1.6.3/node_modules/turbo: Running postinstall script, done in 309ms

devDependencies:
+ eslint 7.32.0
+ eslint-config-custom 0.0.0 <- packages/eslint-config-custom
+ prettier 2.8.0
+ turbo 1.6.3

The integrity of 3528 files was checked. This might have caused installation to take longer.
Done in 11.4s

gitにコミット

terminal
git init . && git add . && git commit -m "Init"

ビルドを実行。裏では、turbo run buildが実行されている。

terminal
pnpm build        
実行結果
> @ build /Users/hayato94087/Private/basic
> turbo run build

• Packages in scope: docs, eslint-config-custom, tsconfig, ui, web
• Running build in 5 packages
• Remote caching disabled
docs:build: cache miss, executing 06047ccc3dded664
web:build: cache miss, executing 63d7762db9c2b02d
docs:build: 
docs:build: > docs@1.0.0 build /Users/hayato94087/Private/basic/apps/docs
docs:build: > next build
docs:build: 
web:build: 
web:build: > web@1.0.0 build /Users/hayato94087/Private/basic/apps/web
web:build: > next build
web:build: 
docs:build: info  - Linting and checking validity of types...
web:build: info  - Linting and checking validity of types...
web:build: info  - Creating an optimized production build...
docs:build: info  - Creating an optimized production build...
docs:build: info  - Compiled successfully
docs:build: info  - Collecting page data...
web:build: info  - Compiled successfully
web:build: info  - Collecting page data...
docs:build: info  - Generating static pages (0/3)
web:build: info  - Generating static pages (0/3)
docs:build: info  - Generating static pages (3/3)
web:build: info  - Generating static pages (3/3)
docs:build: info  - Finalizing page optimization...
docs:build: 
docs:build: Route (pages)                              Size     First Load JS
docs:build: ┌ ○ /                                      301 B          73.7 kB
docs:build: └ ○ /404                                   182 B          73.6 kB
docs:build: + First Load JS shared by all              73.4 kB
docs:build:   ├ chunks/framework-b9101039e598d639.js   45.4 kB
docs:build:   ├ chunks/main-8bea7d3e0a9936aa.js        27.1 kB
docs:build:   ├ chunks/pages/_app-dcb1578928351227.js  195 B
docs:build:   └ chunks/webpack-4e7214a60fad8e88.js     712 B
docs:build: 
docs:build: ○  (Static)  automatically rendered as static HTML (uses no initial props)
docs:build: 
web:build: info  - Finalizing page optimization...
web:build: 
web:build: Route (pages)                              Size     First Load JS
web:build: ┌ ○ / (321 ms)                             300 B          73.7 kB
web:build: └ ○ /404                                   182 B          73.6 kB
web:build: + First Load JS shared by all              73.4 kB
web:build:   ├ chunks/framework-b9101039e598d639.js   45.4 kB
web:build:   ├ chunks/main-8bea7d3e0a9936aa.js        27.1 kB
web:build:   ├ chunks/pages/_app-dcb1578928351227.js  195 B
web:build:   └ chunks/webpack-4e7214a60fad8e88.js     712 B
web:build: 
web:build: ○  (Static)  automatically rendered as static HTML (uses no initial props)
web:build: 

 Tasks:    2 successful, 2 total
Cached:    0 cached, 2 total
  Time:    11.83s 

turbo build lintbuildlintを同時に実行

turbo build lint  
実行結果
╭──────────────────────────────────────────────────────────────────────╮
│                                                                      │
│                   Update available v1.6.3 ≫ v1.8.3                   │
│    Changelog: https://github.com/vercel/turbo/releases/tag/v1.8.3    │
│              Run "npx @turbo/codemod update" to update               │
│                                                                      │
│     Follow @turborepo for updates: https://twitter.com/turborepo     │
╰──────────────────────────────────────────────────────────────────────╯
• Packages in scope: docs, eslint-config-custom, tsconfig, ui, web
• Running build, lint in 5 packages
• Remote caching disabled
web:lint: cache miss, executing df4b9e398e682423
docs:lint: cache miss, executing 5641aa3da27a73b0
ui:lint: cache miss, executing 413abc03146f61e5
docs:build: cache hit, replaying output 06047ccc3dded664
docs:build: 
docs:build: > docs@1.0.0 build /Users/hayato94087/Private/basic/apps/docs
docs:build: > next build
docs:build: 
docs:build: info  - Linting and checking validity of types...
docs:build: info  - Creating an optimized production build...
docs:build: info  - Compiled successfully
docs:build: info  - Collecting page data...
docs:build: info  - Generating static pages (0/3)
docs:build: info  - Generating static pages (3/3)
docs:build: info  - Finalizing page optimization...
docs:build: 
docs:build: Route (pages)                              Size     First Load JS
docs:build: ┌ ○ /                                      301 B          73.7 kB
docs:build: └ ○ /404                                   182 B          73.6 kB
docs:build: + First Load JS shared by all              73.4 kB
docs:build:   ├ chunks/framework-b9101039e598d639.js   45.4 kB
docs:build:   ├ chunks/main-8bea7d3e0a9936aa.js        27.1 kB
docs:build:   ├ chunks/pages/_app-dcb1578928351227.js  195 B
docs:build:   └ chunks/webpack-4e7214a60fad8e88.js     712 B
docs:build: 
docs:build: ○  (Static)  automatically rendered as static HTML (uses no initial props)
docs:build: 
web:build: cache hit, replaying output 63d7762db9c2b02d
web:build: 
web:build: > web@1.0.0 build /Users/hayato94087/Private/basic/apps/web
web:build: > next build
web:build: 
web:build: info  - Linting and checking validity of types...
web:build: info  - Creating an optimized production build...
web:build: info  - Compiled successfully
web:build: info  - Collecting page data...
web:build: info  - Generating static pages (0/3)
web:build: info  - Generating static pages (3/3)
web:build: info  - Finalizing page optimization...
web:build: 
web:build: Route (pages)                              Size     First Load JS
web:build: ┌ ○ / (321 ms)                             300 B          73.7 kB
web:build: └ ○ /404                                   182 B          73.6 kB
web:build: + First Load JS shared by all              73.4 kB
web:build:   ├ chunks/framework-b9101039e598d639.js   45.4 kB
web:build:   ├ chunks/main-8bea7d3e0a9936aa.js        27.1 kB
web:build:   ├ chunks/pages/_app-dcb1578928351227.js  195 B
web:build:   └ chunks/webpack-4e7214a60fad8e88.js     712 B
web:build: 
web:build: ○  (Static)  automatically rendered as static HTML (uses no initial props)
web:build: 
ui:lint: 
ui:lint: > ui@0.0.0 lint /Users/hayato94087/Private/basic/packages/ui
ui:lint: > eslint "**/*.ts*"
ui:lint: 
docs:lint: 
docs:lint: > docs@1.0.0 lint /Users/hayato94087/Private/basic/apps/docs
docs:lint: > next lint
docs:lint: 
web:lint: 
web:lint: > web@1.0.0 lint /Users/hayato94087/Private/basic/apps/web
web:lint: > next lint
web:lint: 
docs:lint: ✔ No ESLint warnings or errors
web:lint: ✔ No ESLint warnings or errors

 Tasks:    5 successful, 5 total
Cached:    2 cached, 5 total
  Time:    3.823s

ローカルで実行

terminal
pnpm dev
実行結果
> @ dev /Users/hayato94087/Private/basic
> turbo run dev

• Packages in scope: docs, eslint-config-custom, tsconfig, ui, web
• Running dev in 5 packages
• Remote caching disabled
docs:dev: cache bypass, force executing b07710f52b24e14c
web:dev: cache bypass, force executing c1543416d4cef438
web:dev: 
web:dev: > web@1.0.0 dev /Users/hayato94087/Private/basic/apps/web
web:dev: > next dev
web:dev: 
docs:dev: 
docs:dev: > docs@1.0.0 dev /Users/hayato94087/Private/basic/apps/docs
docs:dev: > next dev --port 3001
docs:dev: 
docs:dev: ready - started server on 0.0.0.0:3001, url: http://localhost:3001
web:dev: ready - started server on 0.0.0.0:3000, url: http://localhost:3000
docs:dev: event - compiled client and server successfully in 505 ms (150 modules)
web:dev: event - compiled client and server successfully in 515 ms (150 modules)

環境変数?

環境変数はどうなってるのかなと思い調べたら、

We currently recommend using dotenv-cli as the simplest way to bring your environment variables into your development tasks.

つまり、環境変数を開発環境に取り込む最も簡単な方法として dotenv-cli を使用することらしい。

https://turbo.build/repo/docs/handbook/environment-variables

Vercelへデプロイ

以下を参照し、デプロイ方法を確認
https://tech-blog.s-yoshiki.com/entry/305

GitHubのリポジトリを追加

「Configure Project」の「Root Directory」でデプロイ対象となるプロジェクトを指定できる。

「Configure Project」の「Root Directory」でデプロイ対象となるプロジェクトを指定できる。

hayato94087hayato94087

Turborepo with Tailwind

はじめに

TurborepoにTailwindCSSが組み込まれている以下の公式のサンプルを試してみます。

https://github.com/vercel/turbo/tree/main/examples/with-tailwind

公式サンプルの中身

TailwindCSSに関係する情報を記載します。

  • apps/docs
    • TailwindCSSが組み込まれている1つ目のNext.jsアプリケーション
    • TailwindCSSの設定は、packages/tailwind-configを参照しています。
  • apps/web
    • TailwindCSSが組み込まれている2つ目のNext.jsアプリケーション
    • TailwindCSSの設定は、packages/tailwind-configを参照しています。
  • packages/tailwind-config
    • 2つのアプリケーションのTailwindCSSの設定
  • package.json
    • rootのパッケージにTailwindのフォーマットに必要なパッケージを追加しています。

インストール

リポジトリをローカルにダウンロードします。

npx degit vercel/turbo/examples/with-tailwind with-tailwind
cd with-tailwind
pnpm install
git init . && git add . && git commit -m "Init"

VS Codeで開く

VSCodeで開きます。

code .

下記の通りエラーメッセージが出てきます。

Cannot find module 'ui' or its corresponding type declarations.

ビルドする

buildlintを実行します。

turbo build lint
実行結果
 Tasks:    5 successful, 5 total
Cached:    0 cached, 5 total
  Time:    14.654s 

エラーメッセージが消えてます。buildを実行することで消えました。

実行する

pnpm devを実行することでturbo devが実行され、2つのプロジェクトが開発環境で実行されます。

pnpm dev

プロジェクトの構成

改めて、以下が重要な構成です。

  • apps/docs
    • TailwindCSSが組み込まれている1つ目のNext.jsアプリケーション
    • TailwindCSSの設定は、packages/tailwind-configを参照しています。
  • apps/web
    • TailwindCSSが組み込まれている2つ目のNext.jsアプリケーション
    • TailwindCSSの設定は、packages/tailwind-configを参照しています。
  • packages/tailwind-config
    • 2つのアプリケーションのTailwindCSSの設定
  • package.json
    • rootのパッケージにTailwindのフォーマットに必要なパッケージを追加しています。

packages/tailwind-config

2つのアプリケーションの共通のTailwindCSSの設定を確認します。

パッケージの中身です。

packages/tailwind-config/package.json
{
  "name": "tailwind-config",
  "version": "0.0.0",
  "private": true,
  "main": "index.js",
  "devDependencies": {
    "tailwindcss": "^3.2.4"
  }
}

TailwindCSSの設定です。
この設定がwebプロジェクトとdocsプロジェクトの両方に反映されます。

packages/tailwind-config/tailwind.config.js
const colors = require("tailwindcss/colors");

module.exports = {
  content: [
    // app content
    `src/**/*.{js,ts,jsx,tsx}`,
    // include packages if not transpiling
    // "../../packages/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        brandblue: colors.blue[500],
        brandred: colors.red[500],
      },
    },
  },
  plugins: [],
};

apps/docs と apps/web

apps/docs/package.jsonの中身を確認します。
以下の部分が、TailwindCSSに関連する部分。

package.json
  "devDependencies": {
    "autoprefixer": "^10.4.13",
    "postcss": "^8.4.20",
    "tailwind-config": "workspace:*",
    "tailwindcss": "^3.2.4",
  }

TailwindCSSの設定は、tailwind-configを参照するようになっている。

tailwind.config.js
// tailwind config is required for editor support

module.exports = require("tailwind-config/tailwind.config.js");

ルートのpackage.json

ルートのパッケージには、フォーマッターで利用する、prettierのTailwindCSS用のプラグインが入っています。

https://github.com/tailwindlabs/prettier-plugin-tailwindcss

package.json
    "prettier-plugin-tailwindcss": "^0.1.11",

まとめ

TurberepoでTailwindCSSを入れるための構成をサンプルから学びました。

hayato94087hayato94087

Turborepo with Prisma

はじめに

TurberepoをPrismaとつかう方法を学びます。

以下がフォルダ構成

  • apps/web
    • Next.js appのアプリ
  • database: Prisma ORM wrapper to manage & access your database
    tsconfig: tsconfig.jsons used throughout the monorepo

インストール

npx degit vercel/turbo/examples/with-prisma with-prisma
cd with-prisma
pnpm install
git init . && git add . && git commit -m "Init"

ビルド

pnpm build

作業中

hayato94087hayato94087

package.json

スクリプト

{
  "scripts": {
    "clean": "git clean -xdf node_modules",
    "clean:workspaces": "turbo clean",
  },
}
hayato94087hayato94087

TypeScript

TypeScriptのバージョン

全てのワークスペースのTypeScriptのバージョンは可能な限り同一にしておく。VSCodeのエディターで使えるTypeScriptのバージョンは1つのため。

package.json
{
  "devDependencies": {
    "typescript": "4.9.5"
  }
}

TypeScriptのエラーがでたら、

ローカルのタイプスクリプトのサーバを再起動する。

hayato94087hayato94087

謎エラー

よくわからんエラー。

$ npm build
web:build: unhandledRejection Error: Cannot find module '../../next@13.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/shared/lib/constants.js'
web:build: Require stack:
web:build: - /Users/hayato94087/Private/next-sample/apps/web/.next/server/pages/_document.js
web:build: - /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/require.js
web:build: - /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/load-components.js
web:build: - /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js
web:build: - /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/worker.js
web:build: - /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/jest-worker/processChild.js
web:build:     at Module._resolveFilename (node:internal/modules/cjs/loader:1090:15)
web:build:     at /Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/require-hook.js:180:36
web:build:     at Module._load (node:internal/modules/cjs/loader:934:27)
web:build:     at Module.require (node:internal/modules/cjs/loader:1157:19)
web:build:     at require (node:internal/modules/helpers:119:18)
web:build:     at 4038 (/Users/hayato94087/Private/next-sample/apps/web/.next/server/pages/_document.js:895:18)
web:build:     at __webpack_require__ (/Users/hayato94087/Private/next-sample/apps/web/.next/server/webpack-runtime.js:25:42)
web:build:     at 5137 (/Users/hayato94087/Private/next-sample/apps/web/.next/server/pages/_document.js:43:20)
web:build:     at __webpack_require__ (/Users/hayato94087/Private/next-sample/apps/web/.next/server/webpack-runtime.js:25:42)
web:build:     at __webpack_exec__ (/Users/hayato94087/Private/next-sample/apps/web/.next/server/pages/_document.js:926:39) {
web:build:   type: 'Error',
web:build:   code: 'MODULE_NOT_FOUND',
web:build:   requireStack: [
web:build:     '/Users/hayato94087/Private/next-sample/apps/web/.next/server/pages/_document.js',
web:build:     '/Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/require.js',
web:build:     '/Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/load-components.js',
web:build:     '/Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js',
web:build:     '/Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/worker.js',
web:build:     '/Users/hayato94087/Private/next-sample/node_modules/.pnpm/next@13.4.1_@opentelemetry+api@1.4.1_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/jest-worker/processChild.js'
web:build:   ]
web:build: }
web:build:  ELIFECYCLE  Command failed with exit code 1.
web:build: ERROR: command finished with error: command (/Users/hayato94087/Private/next-sample/apps/web) pnpm run build exited (1)
command (/Users/hayato94087/Private/next-sample/apps/web) pnpm run build exited (1)

解消方法は、

$ pnpm clean
$ pnpm clean:workspaes