513 測定値
513 測定値

堅牢な JS/TS モノレポの構築: Yarn、NX、チェンジセットを使用したベストプラクティス

Teimur Gasanov22m2025/03/24
Read on Terminal Reader

長すぎる; 読むには

この記事では、ワークスペース用の Yarn v4、効率的なスクリプト実行と依存関係管理用の NX、および自動バージョン管理とリリース用の Changesets を使用して、堅牢な JS/TS モノレポを構築する方法について説明します。また、コードをアプリ、機能、ライブラリに構造化する方法や、コードの品質を確保してデプロイメントを効率化するための CI/CD 用の GitHub Actions の統合についても説明します。
featured image - 堅牢な JS/TS モノレポの構築: Yarn、NX、チェンジセットを使用したベストプラクティス
Teimur Gasanov HackerNoon profile picture
0-item
1-item

導入

なぜモノレポなのか?

今日、ソフトウェア開発の急速な進化は否定できません。チームは成長し、プロジェクトはより複雑になる傾向にあります。企業は、多くの断片で構成される分散コードベースを維持するために多大なリソースを費やしています。そこで、すべてのコードをまとめる単一の統合リポジトリであるモノレポが登場します。モノレポはトレンドではなく、最近ではコードベース全体を 1 か所に格納するアーキテクチャ アプローチになっています。チームは、強化されたコンテキスト共有、スムーズなコラボレーション、そして自然にコードの再利用を促すツールを手に入れることができます。

Yarn ワークスペースの設定

注: この記事全体で「Yarn」と記載されている場合は、機能が強化され、パフォーマンスが向上した最新バージョンの Yarn v4 を指します。

Yarn ワークスペースとは何ですか?

ワークスペースはモノレポのパッケージであり、パッケージとも呼ばれます。ワークスペースを使用すると、1 つのリポジトリで複数のパッケージを簡単に管理できます。ワークスペースを使用すると、次のことが可能になります。

  • 依存関係を簡単に共有:

    プロジェクト全体で共通の依存関係をシームレスに共有します。

  • 依存関係管理を簡素化:

    Yarn はローカル パッケージを自動的にリンクし、重複を減らして開発を容易にします。

  • インストールを高速化:

    Yarn のパフォーマンス最適化とキャッシュ メカニズム (つまり、組み込みのプラグ アンド プレイ) のメリットを享受できます。

  • モノレポの制御を向上:

    制約(ルール) を定義し、利用可能な多数のプラグインを使用して一貫性を維持します。


この記事では、そのシンプルさ、スピード、および幅広い構成オプションから Yarn をマネージャーとして選択しましたが、適切な選択はプロジェクトの特定のニーズ、チームの好み、および全体的なワークフローによって異なることに留意することが重要です。たとえば、 PNPMTurborepo は、幅広い機能を提供する他の最新ツールです。

初期設定

Yarn のセットアップは簡単なプロセスです。公式ガイドに従って、プロジェクトに Yarn をインストールして構成します: Yarn インストール ガイド

インストールが完了したら、設定に移りましょう。プラグアンドプレイを使用しているため、IDE が依存関係を正しく認識していることを確認する必要があります。VSCode を使用している場合は、次を実行します。

 # Typescript is required for VSCode SDK to set up correctly yarn add -D typescript@^5 yarn dlx @yarnpkg/sdks vscode

別のコード エディターを使用している場合は、 Yarn Editor SDKで利用可能な SDK を確認してください。

この時点で、Yarn の使用を開始する準備が整いました。

モノレポ構造の整理

パッケージ マネージャーが構成されたので、次はスケーラブルなプロジェクト構成を設計します。明確で明確に定義された構造は、リポジトリのナビゲートを容易にするだけでなく、コードの再利用を促進します。この例では、コードベースを 3 つの主要なカテゴリに分割します。

  • アプリ:

    • クライアント: 最終的な展開可能なクライアント製品が含まれます。
    • サーバー: 最終的な展開可能なサーバー製品が含まれます。
  • 特徴

    • クライアント: スタンドアロン UI ウィジェット用。
    • サーバー: スタンドアロンのバックエンド ビジネス ロジック部分用。
  • リブス:

    デザイン システム コンポーネント、定数、アセット、ユーティリティなどの共有コードを格納します。これは、再利用可能なロジックを格納するためのコンテキストフリー ゾーンです。


このフォルダー構造の威力を示すために、まずこれらの主要なフォルダーを Yarn のワークスペース リストに追加してみましょう。ルート package.json に次の内容を追加します。

 "workspaces": [ "apps/**", "features/**", "libs/**" ]

この設定により、Yarn はこれらのフォルダー内のパッケージをローカル パッケージとして扱うようになります。以降のインストールでは、各パッケージの依存関係が適切に設定され、リンクされるようになります。

コードベースのブートストラップ

このセクションでは、モノレポをブートストラップする方法を示す最小限のコードベースの例を説明します。完全なコード スニペットを含める代わりに、この記事専用に作成されたリポジトリ内の完全なファイルへのリンクを含む短い例を提供します。

サーバーアプリケーションのブートストラップ

まず、ユーザー認証用のシンプルなExpress APIから始めます。このサーバー アプリケーションは、別のパッケージのハンドラーを利用する単一のエンドポイント ( /auth/signIn ) を公開します。

 import express from "express"; import cors from "cors"; import { signInHandler } from "@robust-monorepo-yarn-nx-changesets/sign-in-handler"; const app = express(); const port = process.env.PORT || 1234; app.use(express.json()); app.use( cors({ origin: process.env.CORS_ORIGIN || "http://localhost:3000", }) ); app.post("/auth/signIn", signInHandler); app.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); });

パッケージへのリンク


ご覧のとおり、 /auth/signInエンドポイントは別のパッケージからインポートされたハンドラーを使用します。これで、次のコンポーネントであるサーバー機能に移ります。

ブートストラップサーバー機能

サーバー機能は認証ロジックをカプセル化します。このパッケージでは、ライブラリの共有検証ユーティリティを活用するサインイン ハンドラーを定義します。

 import type { RequestHandler } from "express"; import { passwordValidator, usernameValidator, } from "@robust-monorepo-yarn-nx-changesets/validator"; const signInHandler: RequestHandler = (req, res) => { if (!req.body) { res.status(422).send("Request body is missing"); return; } if (typeof req.body !== "object") { res.status(422).send("Request body expected to be an object"); return; } const { username, password } = req.body; const usernameValidationResult = usernameValidator(username); if (typeof usernameValidationResult === "string") { res .status(422) .send("Invalid username format: " + usernameValidationResult); return; } const passwordValidationResult = passwordValidator(password); if (typeof passwordValidationResult === "string") { res .status(422) .send("Invalid password format: " + passwordValidationResult); return; } // Emulate a successful sign-in if (username === "test" && password === "test1234") { res.status(200).send("Sign in successful"); return; } return res.status(422).send("Username or password is incorrect"); }; export default signInHandler;

パッケージへのリンク


このアプローチでは、認証ロジックを独自のパッケージ内にまとめ、独立して開発および保守できるようにします。検証ユーティリティが 共有ライブラリからインポートされる方法に注目してください。

クライアントアプリケーションのブートストラップ

次に、クライアント側を見てみましょう。クライアント アプリケーションでは、サーバー API を呼び出してユーザー認証を可能にするシンプルな Web サイトを構築します。

 "use client"; import { SignInForm } from "@robust-monorepo-yarn-nx-changesets/sign-in-form"; const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:1234"; export default function Home() { const handleSubmit = async (username: string, password: string) => { const response = await fetch(`${API_URL}/auth/signIn`, { method: "POST", body: JSON.stringify({ username, password }), headers: { "Content-Type": "application/json", }, }); if (response.status === 200) { alert("Sign in successful"); return; } if (response.status === 422) { alert("Sign in failed: " + (await response.text())); return; } alert("Sign in failed"); }; return ( <div className="w-full h-screen overflow-hidden flex items-center justify-center"> <SignInForm onSubmit={handleSubmit} /> </div> ); }

パッケージへのリンク

この例では、 SignInFormコンポーネントがクライアント機能パッケージからインポートされ、最終的なコンポーネントにつながります。

ブートストラップクライアント機能

クライアント機能パッケージは、共有検証ロジックとともに認証フォームを提供します。これにより、コードの重複が回避され、一貫性が確保されます。

 import { passwordValidator, usernameValidator, } from "@robust-monorepo-yarn-nx-changesets/validator"; interface SignInFormProps { onSubmit: (username: string, password: string) => void; } const SignInForm = ({ onSubmit }: SignInFormProps) => { const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const username = (event.currentTarget[0] as HTMLInputElement).value; const usernameValidationResult = usernameValidator(username); if (typeof usernameValidationResult === "string") { alert(usernameValidationResult); return; } const password = (event.currentTarget[1] as HTMLInputElement).value; const passwordValidationResult = passwordValidator(password); if (typeof passwordValidationResult === "string") { alert(passwordValidationResult); return; } onSubmit(username!, password!); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" /> <input type="password" placeholder="Password" /> <button type="submit">Submit</button> </form> ); }; export default SignInForm;

パッケージへのリンク


ここでも、共有ライブラリの バリデーターが使用され、検証ロジックが集中化され、簡単に保守できることが保証されます。


最小限のコードベースの例はこれで終わりです。このコードは、モノレポ内のアプリ、機能、ライブラリ間の基本構造と相互接続を示すための簡略化された図解であることに留意してください。プロジェクトの特定の要件に合わせて、必要に応じてこれらの例を拡張できます。

NXでスクリプトを実行する

モノレポでスクリプトを管理するのは難しい場合があります。Yarn を使用すると、さまざまな条件を使用して複数のパッケージでスクリプトを実行できますが、よりきめ細かな制御を行うにはカスタム スクリプトが必要になる場合があります。ここで NX の出番です。NX は、効率的でターゲットを絞ったスクリプト実行のためのすぐに使用できるソリューションを提供します。

NXの紹介

NX は、高度な CI 機能を備えたモノレポ向けに最適化されたビルド システムです。NX を使用すると、次のことが可能になります。

  • タスクを効率的に並行して実行: 同時実行性を活用してビルドを高速化します。
  • 依存関係を特定する: パッケージとスクリプト間の接続を理解します。
  • スクリプト実行結果をキャッシュする: 出力をキャッシュすることで冗長な作業を回避します。
  • プラグインによる動作のカスタマイズ:豊富なプラグインのエコシステムを通じて機能を拡張します。

標的型スクリプト実行

NX の機能を活用するには、まずnx.jsonファイルを作成して、スクリプトのルールセットを定義する必要があります。以下は構成例です。

 { "targetDefaults": { "build": { "dependsOn": [ "^build" ], "outputs": [ "{projectRoot}/dist" ], "cache": true }, "typecheck": { "dependsOn": [ "^build", "^typecheck" ] }, "lint": { "dependsOn": [ "^build", "^lint" ] } }, "defaultBase": "main" }

簡単に言えば、この構成は次のことを意味します。

  • 建てる

    パッケージのbuildスクリプトは依存関係のビルドが成功することに依存し、その出力はキャッシュされます。

  • 型チェック

    パッケージのtypecheckスクリプトは、依存関係のビルド スクリプトと型チェック スクリプトの両方に依存します。

  • 糸くず

    パッケージのlintスクリプトは、依存関係のビルド スクリプトと lint スクリプトの両方に依存します。


次に、 package.jsonにスクリプトを追加しましょう。

 "scripts": { "build:all": "yarn nx run-many -t build", "build:affected": "yarn nx affected -t build --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "typecheck:all": "yarn nx run-many -t typecheck", "typecheck:affected": "yarn nx affected -t typecheck --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "lint:all": "yarn nx run-many -t lint", "lint:affected": "yarn nx affected -t lint --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "quality:all": "yarn nx run-many --targets=typecheck,lint", "quality:affected": "yarn nx affected --targets=typecheck,lint --base=${BASE:-origin/main} --head=${HEAD:-HEAD}" }

ここでは、4 種類の実行スクリプトを定義します。

  • build:パッケージをビルドします。

  • typecheck:パッケージの型をチェックします。

  • lint:パッケージを lint します。

  • 品質:型チェックと lint の両方を実行します。'


各スクリプトには 2 つのバリエーションがあります。

  • all:すべてのパッケージでスクリプトを実行します。
  • 影響を受ける:最近の変更の影響を受けるパッケージに対してのみスクリプトを実行します。 BASEおよびHEAD環境変数を使用すると、範囲 (デフォルトはorigin/mainと現在のHEAD ) を指定できるため、プル リクエストに対してきめ細かな実行が可能になります。これにより、時間とリソースを大幅に節約できます。

循環依存関係の管理

NX には、依存関係の循環の検出に役立つ依存関係グラフを生成する組み込みコマンドも用意されています。次のスクリプトは、NX グラフ出力を使用して循環依存関係をチェックし、見つかった場合は失敗します。

scripts/check-circulardeps.mjsに次の内容のファイルを作成します。

 import { execSync } from "child_process"; import path from "path"; import fs from "fs"; const hasCycle = (node, graph, visited, stack, path) => { if (!visited.has(node)) { visited.add(node); stack.add(node); path.push(node); const dependencies = graph.dependencies[node] || []; for (const dep of dependencies) { const depNode = dep.target; if ( !visited.has(depNode) && hasCycle(depNode, graph, visited, stack, path) ) { return true; } if (stack.has(depNode)) { path.push(depNode); return true; } } } stack.delete(node); path.pop(); return false; }; const getGraph = () => { const cwd = process.cwd(); const tempOutputFilePath = path.join(cwd, "nx-graph.json"); execSync(`nx graph --file=${tempOutputFilePath}`, { encoding: "utf-8", }); const output = fs.readFileSync(tempOutputFilePath, "utf-8"); fs.rmSync(tempOutputFilePath); return JSON.parse(output).graph; }; const checkCircularDeps = () => { const graph = getGraph(); const visited = new Set(); const stack = new Set(); for (const node of Object.keys(graph.dependencies)) { const path = []; if (hasCycle(node, graph, visited, stack, path)) { console.error("🔴 Circular dependency detected:", path.join(" → ")); process.exit(1); } } console.log("✅ No circular dependencies detected."); }; checkCircularDeps();

このスクリプト:

  • NX コマンドを実行して依存関係グラフを生成します。
  • 一時的な JSON ファイルからグラフを読み取ります。
  • 循環を再帰的にチェックします。
  • 循環依存関係が検出された場合は、エラーをログに記録して終了します。

Yarn 制約による依存関係の検証

プロジェクトが大きくなるにつれて、依存関係全体の一貫性を維持することが難しくなります。依存関係、Node バージョン、その他の構成に関する厳格なルールを適用することは、不必要な技術的負債を回避するために不可欠です。Yarn Constraints は、これらの検証を自動化する方法を提供します。

糸の制約を理解する

Yarn Constraints は、モノレポ内のパッケージに対する一連のルールです。これを使用することの大きな利点は、これらのルールの管理者になれることです。たとえば、すべてのパッケージが同じ React バージョンを使用するように強制するルールを作成できます。ルールを設定すれば、ホスト アプリケーションがより高い React バージョンの機能/ライブラリを使用できないという問題が発生することはありません。

大規模なモノレポを依存関係の新しいメジャー バージョンに移行するのは複雑になる可能性がありますが、制約を使用すると、最終的にはプロジェクト全体に一貫性と安定性がもたらされます。

一貫性の強化

サンプル リポジトリでは、次の一貫性を強化するためにyarn.config.cjsファイルを使用します。

  • ノードバージョン

  • 糸バージョン

  • 依存関係のバージョン


移行中に柔軟性を持たせるために、特定のチェックを一時的にバイパスする除外を定義できます。例:

 const workspaceCheckExclusions = []; const dependencyCheckExclusions = [];

これらの定数を使用すると、特定のワークスペースまたは依存関係を検証プロセスから除外して、必要に応じてスムーズな移行を実現できます。

変更セットによるバージョン管理

リポジトリの拡大に伴って直面する可能性があるもう 1 つの問題は、バージョン管理とリリースです。変更セットは、このプロセスを自動化する優れたソリューションを提供し、すべての変更が追跡、バージョン管理、リリースされることを保証します。

変更セットの紹介

Changesets は、モノレポ リポジトリのバージョン管理用に設計されたオープンソース ツールです。変更の意図を捉えた、人間が読める小さなドキュメントに変更を割り当てることで、変更を追跡するプロセスを簡素化します。これらのドキュメントは、変更セットと呼ばれます。主な利点は次のとおりです。

  • 明確なドキュメント

    各変更セットには行われた変更の概要が記載されており、開発者と消費者の両方が新しいリリースで何を期待できるかを理解するのに役立ちます。

  • きめ細かなバージョン管理

    各パッケージは個別にバージョン管理され、影響を受けるパッケージのみが更新されます。これにより、空のバージョンアップや依存関係の破損のリスクが最小限に抑えられます。

  • コラボレーションフレンドリー

    すべての変更は変更セットを通じて記録されるため、チームは実際のリリースの前に更新を確認して承認できます。

リリースの自動化

Changesets の最も強力な機能の 1 つは、プロセスを自動化できることです。Changesets を CI/CD パイプラインに統合すれば、手動でのバージョン変更や NPM の公開は不要になります。

サンプル リポジトリのrelease.yamlワークフローを見てみましょう。create create-release-pull-request-or-publishステップがあります。changesets /action GitHub アクションによってサポートされるステップがすべての魔法を生み出します。パッケージを公開するには、 NPM_TOKENを設定するだけです。その後、 mainブランチへのプッシュごとに次のようになります。

  • 変更セットドキュメントがあるかどうかを確認します

    変更セット ドキュメントが存在する場合、アクションは必要なバージョン バンプと変更ログの更新を含むプル リクエストを作成します。変更が検出されない場合は、何も起こりません。

  • 公開する準備ができているパッケージがあるかどうかを確認します

    パッケージのリリース準備が整っている場合、アクションは提供されたNPM_TOKENを使用して新しいバージョンを NPM に公開します。公開準備が整ったパッケージがない場合、アクションは変更を加えずに終了します。


これらのタスクを自動化することで、Changesets はリリースの一貫性と信頼性を確保し、人為的エラーの可能性を減らし、開発ワークフローを合理化します。

GitHub Actions によるワークフロー統合

このセクションでは、構築したアーキテクチャのパワーを最大限に引き出す方法について詳しく説明します。GitHub Actions を使用して、PR 品質チェック、ライブラリと機能のバージョン リリース、アプリケーションのデプロイメントを自動化します。コードの品質とジョブの粒度を維持しながら自動化を最大化することに重点を置いています。

PR品質の検証

プル リクエスト コードの一貫性と安定性を確保するために、専用のquality.yamlワークフローを作成します。このワークフローは、手動によるバージョン変更が導入されないようにするなど、いくつかのタスクを実行します (バージョン管理は Changesets によって管理されるため)。

 - id: check_version name: Check version changes run: | BASE_BRANCH=${{ github.event.pull_request.base.ref }} git fetch origin $BASE_BRANCH CHANGED_FILES=$(git diff --name-only origin/$BASE_BRANCH HEAD) VERSION_CHANGED=false for FILE in $CHANGED_FILES; do if [[ $FILE == */package.json ]]; then if [ -f "$FILE" ]; then HEAD_VERSION=$(grep '"version":' "$FILE" | awk -F '"' '{print $4}') else continue fi HEAD_VERSION=$(cat $FILE | grep '"version":' | awk -F '"' '{print $4}') if git cat-file -e origin/$BASE_BRANCH:$FILE 2>/dev/null; then BASE_VERSION=$(git show origin/$BASE_BRANCH:$FILE | grep '"version":' | awk -F '"' '{print $4}') else BASE_VERSION=$HEAD_VERSION fi if [ "$BASE_VERSION" != "$HEAD_VERSION" ]; then VERSION_CHANGED=true echo "Version change detected in $FILE" fi fi done if [ "$VERSION_CHANGED" = true ]; then echo "Manual version changes are prohibited. Use changesets instead." exit 1 fi env: GITHUB_REF: ${{ github.ref }}

このチェックに加えて、 check-qualityジョブは依存関係をインストールし、制約を検証し、循環依存関係をチェックし、NX で以前に定義したスクリプトを使用して全体的なコード品質を検証します。

 - id: install-dependencies name: Install dependencies run: yarn --immutable - id: check-constraints name: Check constraints run: yarn constraints - id: check-circulardeps name: Check circular dependencies run: yarn check-circulardeps:all - id: check-quality name: Check quality run: BASE=origin/${{ github.event.pull_request.base.ref }} yarn quality:affected

品質チェックは、現在のプル リクエストの影響を受けるパッケージに対してのみ実行されるように設計されています。これらのジョブが正常に完了すると、プル リクエストがマージする準備が整ったことを示します (コード レビューの受信も行われます)。

プロジェクトに追加のチェックが必要な場合は、ワークフローを変更せずにnx.jsonと品質スクリプトを更新できます。

ライブラリと機能を公開する

PR がマージされた後、リリース ワークフロー (変更セットの章で説明) がトリガーされます。このワークフローは、影響を受けるパッケージをビルドし、バージョンを上げた PR を作成します。この PR が承認され、マージされると、 release.yaml が再度実行されます。今回は、PR を作成する代わりに、バージョンの変更を検出し、更新されたパッケージを NPM にリリースします。

 - id: build-packages name: Build packages run: yarn build:affected - id: create-release-pull-request-or-publish name: Create Release Pull Request or Publish to NPM uses: changesets/action@v1 with: version: yarn changeset version publish: yarn release commit: "chore: publish new release" title: "chore: publish new release" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} release-apps: needs: release-libs-features uses: ./.github/workflows/release-apps.yaml with: publishedPackages: ${{ needs.release-libs-features.outputs.publishedPackages }}

これに続いて、アプリケーションのデプロイメントを担当するrelease-appsというジョブが実行されます。前のステップから公開されたパッケージのリストを受け取り、次の章に進みます。

アプリを公開する

リリース プロセスの最後の部分には、アプリケーションのデプロイが含まれます (アプリケーションはpackage.jsonprivate設定されているため、NPM に公開されません)。 release-apps.yamlワークフローはrelease.yamlによって自動的にトリガーされますが、GitHub の [アクション] タブから直接実行することもできます。

 name: Release Apps on: workflow_call: inputs: publishedPackages: description: "List of published packages" required: false type: string default: "[]" workflow_dispatch: inputs: publishedPackages: description: "List of published packages (optional)" required: false type: string default: "[]"

このワークフローはpublishedPackages入力を受け入れ、どのパッケージが公開されているかを判断します。マトリックス戦略を使用して、マトリックスの各アプリケーションで公開された依存関係の存在を確認します。

 - id: check-dependency-published name: Check if any app dependency is published run: | PUBLISHED_PACKAGES="${{ inputs.publishedPackages }}" PACKAGE_NAME="${{ matrix.package }}" APP="${{ matrix.app }}" DEPENDENCIES=$(jq -r '.dependencies // {} | keys[]' "apps/$APP/package.json") for DEP in $DEPENDENCIES; do if echo "$PUBLISHED_PACKAGES" | grep -w "$DEP"; then echo "published=true" >> $GITHUB_OUTPUT exit 0 fi done echo "published=false" >> $GITHUB_OUTPUT

このチェックは、アプリのデプロイを開始するための 1 つの条件です。もう 1 つの条件は、アプリのバージョンが変更されたことを確認します (依存関係が更新されていなくても再デプロイが必要であることを示します)。

 - id: check-version-change name: Check if app version has changed run: | APP="${{ matrix.app }}" PACKAGE_JSON_PATH="apps/$APP/package.json" CURRENT_VERSION=$(jq -r '.version' "$PACKAGE_JSON_PATH") PREVIOUS_VERSION=$(git show HEAD~1:"$PACKAGE_JSON_PATH" | jq -r '.version' || echo "") if [[ "$CURRENT_VERSION" == "$PREVIOUS_VERSION" ]]; then echo "changed=false" >> $GITHUB_OUTPUT else echo "changed=true" >> $GITHUB_OUTPUT fi

最後に、アプリの依存関係が更新されたか、バージョンが変更されたことを確認した後、ワークフローは新しいバージョンを取得し、アプリケーションのビルドとデプロイに進みます。

 - id: set-up-docker name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - id: get-app-version name: Get the app version from package.json run: echo "app-version=$(cat ./apps/${{ matrix.app }}/package.json | jq -r '.version')" >> $GITHUB_OUTPUT - id: build-image name: Build image if: steps.check-dependency-published.outputs.published == 'true' || steps.check-version-change.outputs.changed == 'true' uses: docker/build-push-action@v4 with: build-contexts: | workspace=./ context: "./apps/${{ matrix.app }}" load: true push: false tags: | ${{ matrix.app }}:v${{ steps.get-app-version.outputs.app-version }}

この例では、Docker イメージをレジストリにプッシュせずにビルドします。実稼働ワークフローでは、この手順を実際のデプロイメント プロセスに置き換えます。

結論

ベストプラクティスの要約

この記事では、堅牢なモノレポのセットアップと、それを効率的に管理するのに役立つツールについて説明しました。コードベースを一元化することで、依存関係の管理が簡素化されるだけでなく、チーム間のコラボレーションも効率化されます。依存関係を共有し、PnP でインストールを高速化し、プロジェクト全体の一貫性を向上させるために Yarn を活用する方法を示しました。さらに、ターゲットを絞ったスクリプト実行のために NX を統合することで、CI が高速かつ効率的になります。変更セットは、バージョン管理を自動化し、手動エラーを減らし、リリースを効率化するのに役立ちました。最後に、必要なタスクのみを実行する GitHub アクションを使用して、本番環境対応の CI/CD パイプラインを作成しました。

次のステップ

  1. 実験と適応: これらのベスト プラクティスをテストするには、まず小規模なモノレポジトリをセットアップすることから始めます。さまざまなフォルダー構造を試し、自信が深まるにつれて徐々に拡張して、より多くのパッケージを含めます。
  2. 追加ツールの統合: プロジェクトの固有の要件とチームの好みに基づいて、PNPM や Turborepo などの補完的なツールを統合することを検討します。
  3. CI/CD パイプラインの強化: GitHub Actions ワークフローを微調整して、プロジェクトに合わせて追加の品質チェック、コード カバレッジ、セキュリティ スキャンを含めます。
  4. コミュニティとアップデート: Yarn、NX、および変更セットの最新リリースを常に最新の状態に保ちます。コミュニティに参加して洞察を共有し、モノレポ管理の新たなトレンドについて学びます。

リソース

  • リポジトリの例:

    このガイド用に作成された完全なサンプル リポジトリにアクセスします。プロジェクト構造、コード サンプル、および実際のモノレポ セットアップを示すスクリプトを調べます。

  • 公開された NPM パッケージ:

    このプロジェクトの一環として公開された実際の NPM パッケージを確認してください。これらのパッケージは、この記事で説明した概念の実際の使用法と実装を示しています。


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks