monorepo實踐:yarn workspace + vite + typescript + react

2023-03-07 18:00:22

前言

最近需要用到多包管理 monorepo 開發新專案,所以提前預研一下專案搭建。

monorepo(monolithic repository)是一種專案架構,就是用一個倉庫管理多個專案(應用,庫),react和babel的原始碼倉庫都是用這種方式在管理。

優缺點略過,可以參考:精讀《Monorepo 的優勢》

因為不需要 npm 發包之類的,所以沒用 lerna,就用 yarn workspace 就可以解決了,技術組合:yarn workspace + vite + typescript + react

使用 yarn workspace 管理 monorepo 的依賴包

通過 yarn workspace 可以管理 monorepo 的共同依賴包

使用命令建立一個根目錄專案 workspace

yarn create vite

這樣我們得到一個簡單的基於 vite+react+ts 的腳手架專案,但其實我們只需要package.jsongitignoretsconfig.jsontsconfig.node.json四個檔案,其他的都刪掉。

workspacepackage.json中加入設定:

"workspaces": [
    "packages/*"
],

這樣便可以宣告我們使用 monorepo 的方式管理 packages 下的多個包。

workspace根目錄下建立 packages 資料夾,然後在 packages 資料夾下執行命令

yarn create vite

建立多個子專案,如:@hanzilu/root、@hanzilu/mobile、@hanzilu/common。

此時我們直接在workspace執行命令安裝 root 專案的依賴:

yarn workspace @hanzilu/root install

我們會發現安裝的依賴包直接安裝在了workspace下的node_modules中,而不是在 @hanzilu/root 專案下。

workspace下執行命令:

 yarn workspace @hanzilu/root dev

就可以啟動 root 資料夾下的專案了。

不過我們不可能一個個去安裝所有子專案,那麼就直接在workspace下執行命令即可:

yarn install

更多的一些常用命令:

  • yarn workspaces info [--json] 顯示當前各個子專案之間的依賴關係樹
  • yarn workspaces add / remove / upgrade [package] 新增、刪除、更新全域性依賴
  • yarn workspace [name] add / remove / upgrade [package] 某個子專案新增、刪除、更新依賴
  • yarn worspace [name] [command] 執行某個專案下的命令

通用的 typescript 設定

上面的專案中並不是共用同一個 typescript 設定的,所以我們需要刪除各個子專案中的tsconfig.jsontsconfig.node.json

然後我們修改workspace下的tsconfig.json中 include 為:

"include":["packages/**/src"],

也就是把 typescript 設定應用到這個目錄下。

同樣的tsconfig.node.json中的設定改為:

"include": ["packages/**/vite.config.ts"]

對本地依賴專案的處理

我們使用多包管理,可能是兩個不同的專案比如 @hanzilu/root 和@hanzilu/ mobile,想要使用統一的元件或者方法,這個方法在我們的 @hanzilu/common 中。

那麼首先改造一下我們的 common 專案,在 package.json 中將新增入口:

"main":"./src/main.tsx",

然後將 main.tsx 內容改為:

const HelloWorld: React.FC = () => {
    return <div className="App">HelloWorld</div>;
};

export default HelloWorld;

現在我們的 common 就是個很簡單的 HelloWorld 元件。

那麼我們怎麼去讓@hanzilu/root 能夠使用到這個元件呢?

我們就像安裝依賴庫一樣執行命令:

yarn workspace @hanzilu/root add @hanzilu/[email protected]

參照的時候也和依賴庫一樣:

import HelloWorld from "@hanzilu/common";

但是到了這一步你的 typescript 提示會報錯,你需要在workspace下的 tsconfig.json 加上這段設定:

"compilerOptions": {
    //...
    "baseUrl": "./",
    "paths": {
        "@hanzilu/*": ["packages/*"]
    },
}

去告訴 typescript,@hanzilu/系列的包實際上是用的原生的 packages 目錄下的內容。

至此,我們就可以正常進行專案的開發了。

簡化命令列

在進行上面操作的時候,應該會明顯感覺到命令列太長,輸入太繁瑣。

所以我們需要在 package.json 中對常用的命令,進行簡化:

"root": "yarn workspace @hanzilu/root", // 簡化命令
"mobile":"yarn workspace @hanzilu/mobile",
"dev:root": "yarn root dev",  // 開發root
"dev:mobile": "yarn mobile dev",
"build:root": "yarn root build", // 構建root
"build:mobile": "yarn mobile build"

總結

總體而言沒遇到什麼大問題,挺好用的,可能也跟剛接觸不知坑之深淺有關。

關於 react 和 vite 的部分直接省略了,如果想要了解可以檢視我的這篇文章:Vite+React 搭建開發構建環境實踐