[TS] Setup TypeScript Monorepo Template
此篇為各筆記之整理,非原創內容,資料來源可見下方連結與文後參考資料:
- JavaScript and TypeScript Monorepos @ Frontend Master by Mike North
- How to Setup a TypeScript project using Rollup.js @ This Dot
monorepos 指的是在一個 git repository 中有多個 libraries/projects 在內,而不是把它拆成多個獨立的 git repository 去維護。
專案位置:pjchender/typescript-monorepo-template 另一個可參考的:fem-fullstack-ts
workspaces: setup with yarn
@@ -1,9 +1,12 @@
{
"name": "js-ts-monorepos",
"version": "1.0.0",
"main": "index.js",
"repository": "git@github.com:mike-north/js-ts-monorepos.git",
"author": "Mike North <michael.l.north@gmail.com>",
"license": "BSD-2-Clause",
- "private": true
+ "private": true,
+ "workspaces": [
+ "packages/*"
+ ]
}
在 npm 7 之後也有支援 workspaces,用法可以參考最下方的補充。
如果是多個不同性質的專案,可以設定成類似:
// package.json
{
"workspaces": ["client", "server", "shared"]
}
typescript: composite project
composite @ TypeScript > tsconfig
下述設定方式適合用在透過 tsc 編譯專案時,若是用其他編譯工具需自行調整。
我們不需要在每個 libraries/projects 中都建立各自的 tsconfig.json
,而是可以把它定義在一個地方,library 內的 tsconfig 就去繼承它就好。
在 tsconfig.json
的 compilerOptions
中加上 composite: true
表示它是其中一部分的設定檔,加上這個項目後:
- 若沒有指定
rootDir
預設會是帶有tsconfig.json
檔案的那個目錄 - 套用此項目的檔案一定要有
include
和files
declaration
預設會是true
{
"extends": "../tsconfig.settings.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src"
]
}
執行 tsc
打包專案後,專案中會出現一支 tsconfig.tsbuildinfo
,這支檔案用來告訴 TypeScript 打包好的檔案和當前的原始碼(source code)是否一致。
實作步驟
-
在
packages
資料夾中建立tsconfig.settings.json
,這支檔案是要讓packages/types
和packages/utils
裡面的tsconfig.json
繼承用的// packages/tsconfig.settings.json
// 給 packages/ 中的 tsconfig 讀取用的共用設定檔
{
"compilerOptions": {
"module": "CommonJS",
"types": [],
"sourceMap": true,
"target": "ES2018",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"declaration": true
}
} -
packages/types/tsconfig.json
和packages/utils/tsconfig.json
則可以直接繼承packages/tsconfig.settings.json
,另外因為這裡面只是一部分的設定擋,所以要加上composite: true
// packages/types/tsconfig.json
// packages/utils/tsconfig.json
{
"extends": "../tsconfig.settings.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
} -
packages/tsconfig.json
則是打包檔案執行tsc -b .
時執行會吃的 TypeScript 設定檔:// packages/tsconfig.json
// tsc 會執行的 root 是這隻
// 這支會對所有的 packages 打包所有必要的檔案
{
"files": [], // 只需針對 packages 內的程式碼執行 build,而不需要針對 packages 內的所有檔案都產生對應的 .js 檔
"references": [
{
"path": "utils"
},
{
"path": "types"
}
]
} -
在
packages/types/package.json
和packages/utils/package.json
中添加測試用的 script:// packages/types/package.json
// packages/utils/package.json
"scripts": {
+ "build": "tsc -b .",
},
最終的專案結構會長像這樣:
├── package.json
├── packages
│ ├── tsconfig.json
│ ├── tsconfig.settings.json
│ ├── types
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── utils
│ ├── package.json
│ └── tsconfig.json
├── tsconfig.json
只需專案的「根目錄」執行 yarn tsc -b packages
,即會針對 packages
資料夾中的每個 package 進行打包。
執行 tsc -b packages
時,會使用 packages/tsconfig.json
這支檔案。
testing: setup jest with babel
延伸閱讀:
- config-files#monorepos @ babeljs
建立 packages/.babelrc
:
// packages/.babelrc
{
"presets": [
[
"@babel/preset-env",
{
// babel 會打包成相容於 node 12 的程式碼
"targets": {
"node": 12
}
}
],
"@babel/preset-typescript"
]
}
接著建立 packages/types/.babelrc
和 packages/utils/.babelrc
,讓他們的設定檔都繼承自 packages/.babelrc
:
// packages/types/.babelrc
// packages/utils/.babelrc
{
"extends": "../.babelrc"
}
在 packages/types/package.json
和 packages/utils/package.json
中添加測試用的 script:
// packages/types/package.json
// packages/utils/package.json
"scripts": {
+ "test": "jest",
},
最終的資料夾結構長這樣:
├── packages
│ ├── .babelrc
│ ├── tsconfig.json
│ ├── tsconfig.settings.json
│ ├── types
│ │ ├── .babelrc
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── utils
│ ├── .babelrc
│ ├── package.json
│ └── tsconfig.json
└── tsconfig.json
linter: setup ESLint
Mike North 根據過去經驗,強烈建議把 eslint 的設定擋放在專案的根目錄(.
)而不是 packages
這個 workspaces 中,避免有些編輯器找不到 eslint 的設定。以 VSCode 來說,它只會認得一個 eslint 的設定,而沒辦法知道不同 workspaces 內的 package 要套用不同的 eslint 設定。因此,ESLint 的設定會是 workspaces level 的,一個設定檔會適用所有的 workspaces 內的所有 packages。
實作步驟
-
安裝 eslint 和 @typescript-eslint
# -W 是指安裝在 workspaces
$ yarn add -WD eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser -
在根目錄建立
.eslintrc
,這支會給編輯器和其他 packages 中的 .eslintrc 使用// ./eslintrc
{
"env": {
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12
},
"plugins": ["@typescript-eslint"],
"rules": {
"prefer-const": "error",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-assignment": "off"
}
}