Turborepo
Turbo - 1プロジェクトでの利用
はじめに
以下の公式ページに記載の内容でTurborepoをNext.jsで試してみました。
Turboのインストール
Turboをグローバルにインストール
yarn global add turbo
作業環境に移動
cd /Users/hayato94087/Private/turborepo
Next.jsをインストール
Next.jsを作成
yarn create next-app nextjs-turbo-1 --typescript --eslint --src-dir --import-alias "@/*"
cd nextjs-turbo-1
yarn
実行環境を設定
turbo.json
を作成します。
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"outputs": [".next/**"]
},
"lint": {}
}
}
.gitignore
を修正し、.turbo
を無視するよう設定します。
+ # turbo
+ .turbo
Turboを実行
build
とlint
をturbo
で実行します。build
とlint
が同時に実行されます。
turbo build lint
実行結果
Tasks: 2 successful, 2 total
Cached: 0 cached, 2 total
Time: 7.13s
開発環境をturbo
で実行させます。
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を利用する方法を記載しました。
以下が作業結果のリポジトリ
複数プロジェクトが入っているサンプルの実行
はじめに
Turborepoの公式サイトで提供されているbasicのexampleをローカルで構築する。
このbasicには複数のシンプルなNext.jsのプロジェクトが入っています。
インストール
リポジトリをローカルに作成
npx degit vercel/turbo/examples/basic basic
cd basic
パッケージをインストール
pnpm i
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にコミット
git init . && git add . && git commit -m "Init"
ビルドを実行。裏では、turbo run build
が実行されている。
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 lint
でbuild
とlint
を同時に実行
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
ローカルで実行
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 を使用することらしい。
Vercelへデプロイ
以下を参照し、デプロイ方法を確認
GitHubのリポジトリを追加
「Configure Project」の「Root Directory」でデプロイ対象となるプロジェクトを指定できる。
「Configure Project」の「Root Directory」でデプロイ対象となるプロジェクトを指定できる。
Turborepo with Tailwind
はじめに
TurborepoにTailwindCSSが組み込まれている以下の公式のサンプルを試してみます。
公式サンプルの中身
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.
ビルドする
build
とlint
を実行します。
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の設定を確認します。
パッケージの中身です。
{
"name": "tailwind-config",
"version": "0.0.0",
"private": true,
"main": "index.js",
"devDependencies": {
"tailwindcss": "^3.2.4"
}
}
TailwindCSSの設定です。
この設定がwebプロジェクトとdocsプロジェクトの両方に反映されます。
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に関連する部分。
"devDependencies": {
"autoprefixer": "^10.4.13",
"postcss": "^8.4.20",
"tailwind-config": "workspace:*",
"tailwindcss": "^3.2.4",
}
TailwindCSSの設定は、tailwind-configを参照するようになっている。
// tailwind config is required for editor support
module.exports = require("tailwind-config/tailwind.config.js");
ルートのpackage.json
ルートのパッケージには、フォーマッターで利用する、prettierのTailwindCSS用のプラグインが入っています。
"prettier-plugin-tailwindcss": "^0.1.11",
まとめ
TurberepoでTailwindCSSを入れるための構成をサンプルから学びました。
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
作業中
モノレポ vs ポリレポ
参考になるリポジトリ
create-t3-turbo
package.json
スクリプト
{
"scripts": {
"clean": "git clean -xdf node_modules",
"clean:workspaces": "turbo clean",
},
}
turbo.json
pipeline
{
"pipeline": {
"clean": {
"cache": false
},
},
}
TypeScript
TypeScriptのバージョン
全てのワークスペースのTypeScriptのバージョンは可能な限り同一にしておく。VSCodeのエディターで使えるTypeScriptのバージョンは1つのため。
{
"devDependencies": {
"typescript": "4.9.5"
}
}
TypeScriptのエラーがでたら、
ローカルのタイプスクリプトのサーバを再起動する。
謎エラー
よくわからんエラー。
$ 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