首頁 >web前端 >js教程 >使用 PNPM 在 Monorepo 中建置並運行您的專案

使用 PNPM 在 Monorepo 中建置並運行您的專案

Patricia Arquette
Patricia Arquette原創
2025-01-19 16:33:12360瀏覽

Build and run your project in Monorepo with PNPM

專案程式碼組織:Polyrepo vs. Monorepo

專案程式碼組織主要有兩種方式:

  1. Polyrepo: 將專案代碼分散在不同的倉庫。這是目前的標準做法,多個團隊分別擁有自己的倉庫、建造產物和流水線,擁有自主權。
  2. Monorepo: 將所有項目代碼集中在一個倉庫。專案被劃分為應用程式和套件,方便程式碼重複使用和共享標準功能,有助於統一第三方包版本、遞歸構建依賴項的原始程式碼以及使用相同的工具進行CI/CD管線。

許多大型科技公司都使用Monorepo,例如Yandex。 Monorepo有助於在團隊和業務部門之間共享創意和最佳實踐。更多關於Monorepo和相關工具的信息,請訪問https://www.php.cn/link/b01ccf4f29b57b0b1bdb9407050db28d。本文將重點放在使用PNPM建立Monorepo的簡單方案。

PNPM使用工作區(workspaces)來整合單一倉庫中的多個項目。

環境搭建

首先,建立一個空資料夾作為新的Monorepo專案。在倉庫內初始化PNPM:

<code class="language-bash">pnpm init</code>

然後,建立一個pnpm-workspace.yaml文件,描述包資料夾:

<code class="language-yaml">// pnpm-workspace.yaml

packages:
  - 'packages/**'
  - 'apps/**'</code>

/packages資料夾存放共用程式庫,/apps資料夾存放應用程式(例如,獨立的React Native行動應用程式和使用相同元件或連接程式庫與API伺服器通訊的Web應用程式)。

本文將使用一個Telegram發布機器人為例,其原始碼位於GitHub:https://www.php.cn/link/8164ca2fe04767628ac1c6813e8a0867。下載並解壓縮到/apps/publish-bot資料夾,然後執行安裝指令:

<code class="language-bash">pnpm install</code>

建立Telegram工具包

/packages資料夾中建立一個名為telegram-utils的資料夾,初始化PNPM和TypeScript:

<code class="language-bash">pnpm init && pnpm add -D typescript && pnpm tsc --init</code>

該套件將提供一個函數,用於組合來自所有訊息(文字、影片和照片)的文字和標題。需要安裝Telegraf包:

<code class="language-bash">pnpm add telegraf</code>

所有原始碼都應位於/src目錄中。為了方便功能分組,建議建立不同的資料夾。組合文字的功能位於/texts資料夾中,程式碼如下:

<code class="language-typescript">// packages/telegram-utils/src/texts/combineTexts.ts

import { Message } from 'telegraf/types';
import { FmtString, join } from 'telegraf/format';

type GroupedMessages = {
    photos: Array<Message.PhotoMessage>;
    videos: Array<Message.VideoMessage>;
    text: Array<Message.TextMessage>;
};

export const combineTexts = ({ photos, videos, text }: GroupedMessages) => {
    const photoTexts = photos
        .map(photo => photo.caption ? new FmtString(photo.caption, photo.caption_entities) : undefined)
        .filter((t): t is Required<FmtString> => t !== undefined);

    const videoTexts = videos
        .map(video => video.caption ? new FmtString(video.caption, video.caption_entities) : undefined)
        .filter((t): t is Required<FmtString> => t !== undefined);

    const allTexts = [];

    if (text.length) allTexts.push(join(text.map(t => new FmtString(t.text, t.entities))), '\n');
    if (photoTexts.length) allTexts.push(join(photoTexts, '\n'));
    if (videoTexts.length) allTexts.push(join(videoTexts, '\n'));

    return join(allTexts, '\n');
};</code>

代碼說明:

  • 函數輸入按類型分組的訊息:照片、影片或文字;
  • 媒體訊息應轉換為包含標題和標題實體的FMT字串。對於後續過濾,應返回undefined
  • 分步連接文字數組,最終將所有文字組合成一條大訊息。

建立/texts資料夾的索引檔:

<code class="language-bash">pnpm init</code>

package.json檔案中使用exports欄位設定套件功能的匯出:

<code class="language-yaml">// pnpm-workspace.yaml

packages:
  - 'packages/**'
  - 'apps/**'</code>

為了在應用程式中辨識Monorepo包,為所有包加上前綴@monorepo。重新命名package.json檔案中的telegram-utils套件:

<code class="language-bash">pnpm install</code>

新增建置腳本:

<code class="language-bash">pnpm init && pnpm add -D typescript && pnpm tsc --init</code>

完整的package.json檔案:

<code class="language-bash">pnpm add telegraf</code>

設定TypeScript編譯器:啟用增量編譯以節省建置時間,僅處理變更的部分;啟用複合編譯以使用專案參考。將/src資料夾定義為rootDir,將套件的outDir定義為/dist。更新後的tsconfig.json

<code class="language-typescript">// packages/telegram-utils/src/texts/combineTexts.ts

import { Message } from 'telegraf/types';
import { FmtString, join } from 'telegraf/format';

type GroupedMessages = {
    photos: Array<Message.PhotoMessage>;
    videos: Array<Message.VideoMessage>;
    text: Array<Message.TextMessage>;
};

export const combineTexts = ({ photos, videos, text }: GroupedMessages) => {
    const photoTexts = photos
        .map(photo => photo.caption ? new FmtString(photo.caption, photo.caption_entities) : undefined)
        .filter((t): t is Required<FmtString> => t !== undefined);

    const videoTexts = videos
        .map(video => video.caption ? new FmtString(video.caption, video.caption_entities) : undefined)
        .filter((t): t is Required<FmtString> => t !== undefined);

    const allTexts = [];

    if (text.length) allTexts.push(join(text.map(t => new FmtString(t.text, t.entities))), '\n');
    if (photoTexts.length) allTexts.push(join(photoTexts, '\n'));
    if (videoTexts.length) allTexts.push(join(videoTexts, '\n'));

    return join(allTexts, '\n');
};</code>

整合

回到/apps/publish-bot,將@monorepo/telegram-utils套件加入依賴項。注意,不需要指定套件版本,使用workspace:*表示:

<code class="language-typescript">// packages/telegram-utils/src/texts/index.ts

export * from './combineTexts';</code>

安裝依賴項:

<code class="language-json">// packages/telegram-utils/package.json

"exports": {
    "./texts": {
        "import": "./src/texts/index.ts",
        "require": "./dist/texts/index.js"
    }
}</code>

更新發布機器人的preview指令:

<code class="language-json">// packages/telegram-utils/package.json

"name": "@monorepo/telegram-utils"</code>

更新/apps/publish-bot/tsconfig.json

<code class="language-json">// packages/telegram-utils/package.json

"scripts": {
    "build": "tsc -p tsconfig.json"
}</code>

在建構應用程式碼前,需要先建置所有依賴項:

<code class="language-json">// packages/telegram-utils/package.json

{
    "name": "@monorepo/telegram-utils",
    "version": "1.0.0",
    "main": "index.js",
    "scripts": {
        "build": "tsc -p tsconfig.json"
    },
    "keywords": [],
    "license": "ISC",
    "exports": {
        "./texts": {
            "import": "./src/texts/index.ts",
            "require": "./dist/texts/index.js"
        }
    },
    "devDependencies": {
        "typescript": "^5.7.3"
    },
    "dependencies": {
        "telegraf": "^4.16.3"
    }
}</code>

總結

現在,發布機器人使用內部共享庫/包,並位於Monorepo中。這使得快速建立新功能和在多個應用程式中重複使用程式碼成為可能。

圖片來自Unsplash的Gabriel Heinzer

以上是使用 PNPM 在 Monorepo 中建置並運行您的專案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn