Yarn Workspaces:像專業人士一樣組織項目的代碼庫

已發表: 2022-03-10
快速總結 ↬ Yarn 工作區讓您可以使用單一存儲庫 (monorepo) 來組織項目代碼庫。 在這篇文章中,Jorge 解釋了為什麼它們是一個很棒的工具,以及如何使用 Yarn 和基本的 npm 腳本創建你的第一個 monorepo,並為每個應用程序添加所需的依賴項。

每當我開始著手一個新項目時,我都會問自己:“我應該為後端服務器和前端客戶端使用單獨的 git 存儲庫嗎? 組織代碼庫的最佳方式是什麼?”

在我的個人網站上工作了幾個月後,我遇到了同樣的問題。 我最初將所有代碼都放在同一個存儲庫中:後端使用 Node.js,前端使用 ES6 和 Pug。 我採用這種組織方式是為了方便,因為將兩個項目放在同一個 repo 中可以很容易地搜索函數和類,並促進重構。 但是,我發現了一些缺點:

  • 沒有獨立部署。
    兩個應用程序都使用相同的package.json ,並且兩個項目沒有明確的分離。
  • 界限不清。
    由於我依賴全局package.json ,我沒有為後端和前端設置特定版本的機制。
  • 無需版本控制的共享實用程序和代碼。

經過一些研究,我發現 Yarn 工作區是解決這些缺點的好工具,它是創建 monorepo 項目的有用工具(稍後會更多!)。

在本文中,我分享了 Yarn 工作區的介紹。 我們將一起完成一個關於如何使用它創建您的第一個項目的教程,最後我們將進行回顧和後續步驟。

跳躍後更多! 繼續往下看↓

什麼是紗線工作區?

Yarn 是 Facebook 的一個包管理器,它有一個很棒的功能,叫做 Yarn 工作區。 Yarn 工作區讓您可以使用單一存儲庫 (monorepo) 來組織項目代碼庫。 這個想法是單個存儲庫將包含多個包。 包是孤立的,可以獨立於更大的項目而存在。

紗線工作區

作為替代方案,我們可以將所有這些包放入單獨的存儲庫中。 不幸的是,這種方法會影響在包及其依賴項目上進行開發時的可共享性、效率和開發人員體驗。 此外,當我們在單個存儲庫中工作時,我們可以更快地移動並構建更具體的工具來改進整個開發生命週期的流程。

Monorepo 項目已被 Google 或 Facebook 等大公司廣泛接受,並且證明 monorepo 可以擴展。

React 是 monorepo 開源項目的一個很好的例子。 此外,React 使用 Yarn 工作區來實現這一目的。 在下一節中,我們將學習如何使用 Yarn 創建我們的第一個 monorepo 項目。

使用 Yarn 工作區通過六個步驟創建一個帶有 React 和 Express 的 Monorepo 項目

到目前為止,我們已經了解了 Yarn 是什麼,monorepo 是什麼,以及為什麼 Yarn 是創建 monorepo 的好工具。 現在讓我們從頭開始學習如何使用 Yarn 工作區設置一個新項目。 要繼續學習,您需要一個安裝了最新 npm 的工作環境。 下載源代碼。

先決條件

要完全完成本教程,您需要在機器上安裝 Yarn。 如果您之前沒有安裝 Yarn,請按照這些說明進行操作。

這些是我們將在本教程中遵循的步驟:

  1. 創建您的項目和根工作區
  2. 創建一個 React 項目並將其添加到工作區列表
  3. 創建一個 Express 項目並將其添加到工作區
  4. 安裝所有依賴項並向 yarn.lock 打個招呼
  5. 使用通配符 (*) 導入所有包
  6. 添加腳本以運行兩個包

1. 創建您的項目和根工作區

在本地機器終端中,創建一個名為example-monorepo的新文件夾:

 $ mkdir example-monorepo

在文件夾中,使用我們的根工作區創建一個新的package.json

 $ cd example-monorepo $ touch package.json

這個包應該是私有的,以防止意外發布根工作區。 將以下代碼添加到新的package.json文件以使包成為私有:

 { "private": true, "name": "example-monorepo", "workspaces": [], "scripts": {} }

2.創建一個React項目並將其添加到工作區列表中

在這一步中,我們將創建一個新的 React 項目並將其添加到根工作空間內的包列表中。

首先,讓我們創建一個名為packages的文件夾,我們將在其中添加我們將在教程中創建的不同項目:

 $ mkdir packages

Facebook 有一個創建新 React 項目的命令: create-react-app 。 我們將使用它來創建一個包含所有必需配置和腳本的新 React 應用程序。 我們正在步驟 1 中創建的文件夾中創建這個名為“client”的新項目。

 $ yarn create react-app packages/client

一旦我們創建了新的 React 項目,我們需要告訴 Yarn 將該項目視為一個工作區。 為此,我們只需在根package.json的“workspaces”列表中添加“client”(我們之前使用的名稱)。 確保使用與運行create-react-app命令時相同的名稱。

 { "private": true, "name": "example-monorepo", "workspaces": ["client"], "scripts": {} }

3. 創建一個 Express 項目並將其添加到工作區

現在是時候添加後端應用了! 我們使用express-generator創建一個包含所有必需配置和腳本的 Express 框架。

確保您的計算機上安裝了express-generator 。 您可以使用 Yarn 使用以下命令安裝它:

 $ yarn global add express-generator --prefix /usr/local

使用express-generator ,我們在文件夾中創建一個名為“server”的新 Express 應用程序。

 $ express --view=pug packages/server

最後,將新包“server”添加到根package.json內的工作區列表中。

 { "private": true, "name": "example-monorepo", "workspaces": ["client", "server"], "scripts": {} }

注意本教程僅使用兩個包(服務器和客戶端)進行了簡化。 在一個項目中,您通常可以擁有所需數量的包,按照慣例,開源社區使用這種命名模式: @your-project-name/package-name例如:我在我的網站上使用@ferreiro/server

4. 安裝所有依賴並向 yarn.lock 打個招呼

一旦我們添加了我們的 React 應用程序以及我們的 Express 服務器,我們需要安裝所有的依賴項。 Yarn 工作空間簡化了這個過程,我們不再需要去每個應用程序手動安裝它們的依賴項。 相反,我們執行一個命令 — yarn install — Yarn 神奇地為每個包安裝所有依賴項,並優化和緩存它們。

運行以下命令:

 $ yarn install

此命令生成一個yarn.lock文件(類似於此示例)。 它包含您項目的所有依賴項,以及每個依賴項的版本號。 Yarn 會自動生成這個文件,你不應該修改它。

5. 使用通配符 (*) 導入所有包

到目前為止,對於我們添加的每個新包,我們還被迫更新根package.json以將新包包含到workspaces:[]列表中。

我們可以使用通配符 (*) 來避免這個手動步驟,它告訴 Yarn 將所有包包含在文件夾中。

在根package.json中,使用以下行更新文件內容: "workspaces": ["packages/*"]

 { "private": true, "name": "example-monorepo", "workspaces": ["packages/*"], "scripts": {} }

6.添加一個腳本來運行這兩個包

最後一步! 我們需要有一種方法來同時運行這兩個包——React 客戶端和 Express 客戶端。 對於這個例子,我們將使用concurrently 。 這個包讓我們可以並行運行多個命令。

concurrently添加到根package.json

 $ yarn add -W concurrently

在根工作區package.json中添加三個新腳本。 兩個腳本分別初始化 React 和 Express 客戶端; 另一個同時使用concurrently運行兩個腳本。 請參閱此代碼以供參考。

 { "private": true, "name": "example-monorepo", "workspaces": ["packages/*"], "scripts": { "client": "yarn workspace client start", "server": "yarn workspace server start", "start": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\" } }

注意我們不需要將start腳本寫入“服務器”和“客戶端”包,因為我們用來生成這些包的工具( create-react-appexpress-generator )已經為我們添加了這些腳本。 所以我們很高興!

最後,確保更新 Express 啟動腳本以在端口 4000 上運行 Express 服務器。否則,客戶端和服務器將嘗試使用相同的端口 (3000)。

轉到packages/server/bin/www並更改第 15 行中的默認端口。

 var port = normalizePort(process.env.PORT || '4000');

現在我們準備好運行我們的包了!

 $ yarn start

從這往哪兒走

讓我們回顧一下我們所涵蓋的內容。 首先,我們了解了 Yarn 工作空間以及為什麼它是創建 monorepo 項目的好工具。 然後,我們使用 Yarn 創建了我們的第一個 JavaScript monorepo 項目,我們將應用程序的邏輯分為多個包:客戶端和服務器。 此外,我們創建了我們的第一個基本 npm 腳本並為每個應用程序添加了所需的依賴項。

從這一點來看,我建議您詳細查看開源項目,了解它們如何使用 Yarn 工作區將項目邏輯拆分為多個包。 反應是一個很好的。

Jorge Ferreiro 的網站使用 yarn 工作區和帶有後端和前端應用程序的包
Jorge Ferreiro 的網站使用 yarn 工作區和帶有後端和前端應用程序的包(大預覽)

另外,如果你想看到一個生產網站使用這種方法將後端和前端應用程序分成獨立的包,你可以查看我的網站的來源,其中還包括一個博客管理員。 當我遷移代碼庫以使用 Yarn 工作區時,我使用 Kyle Wetch 創建了一個拉取請求。

此外,我為使用 React、webpack、Node.js 和 Yarn 工作區的黑客馬拉松項目設置了基礎設施,您可以在此處查看源代碼。

最後,學習如何發布獨立包以熟悉開發生命週期對您來說真的很有趣。 有幾個有趣的教程值得一看:yarn publish 或 npm publish。

如有任何意見或問題,請隨時在 Twitter 上與我聯繫。 此外,在接下來的幾個月裡,我將在我的博客中發布更多關於此的內容,因此您也可以在那裡訂閱。 快樂編碼!