要全自己折腾的话,或许会陷入无尽的坑,所以我选择从 antfu 的 starter-ts 开始,按照自己的习惯进行一些改造。
技術棧選擇#
TypeScript + ESLint + Prettier#
TypeScript 自不必多說,我使用 ESLint 來檢查和格式化代碼。
如果你和 Prettier 的 printWidth
也做過鬥爭並且不能忍受的話,請看 Why I don't use Prettier,可能會喜歡用 ESLint 來格式化代碼,並且我們現在有了 ESLint Stylistic 這種開箱即用的配置。
要了解更多,請查看 為什麼是 ESLint。
pnpm + bunchee + tsx + vitest#
為了方便的測試我們寫的庫,pnpm 的 workspace 是必不可少的,可以很方便的開一個 playground。此外,它默認不提升依賴的特性也能夠防止我們不小心引用了沒有定義的依賴。我的 .npmrc
為:
ignore-workspace-root-check=true
public-hoist-pattern=[]
使用 bunchee 來完成打包任務,它讀取 package.json 中的 exports
字段作為打包的輸入輸出,無需手動指定配置。此外它的 esm 打包結果看起來也更好,tsup 存在 ESM output with CJS content 的問題。
如果你希望更清楚精細的控制打包流程,可以使用 rollup 配合一些插件來自己寫配置。這裡有一些常用的插件推薦。
- rollup-plugin-dts
- rollup-plugin-swc 或者 rollup-plugin-esbuild
- @rollup/plugin-node-resolve
- @rollup/plugin-commonjs
如果你想看看類似 bunchee 的其它選擇,可以看看 unbuild 和 tsup。tsup 的 --dts-resolve
選項在你想要打包一些依賴的時候很有用。
開發過程中,非必要的情況下,基本上沒人想先打包再跑代碼。因此,我使用 tsx 來直接執行 ts 文件,用 vitest 來測試代碼。
正確設置 package.json
#
便捷地維護包的基本信息#
作為一個起手模板,它需要提前寫好包的基本信息,並可以在開一個新坑的時候快速的查找替換。
基本信息處於兩個位置,一個是 package.json
,一個是 README.md
,通過全局替換 pkg-placeholder
和 $description$
可以讓你的包快速就位並發布。
設置包導出的內容#
首先你可以閱讀 Ship ESM & CJS in one Package,Types for Submodules 和 moduleResolution 總結 這幾篇文章來了解同時發布 esm 和 cjs 兩種格式包相關的基礎信息。
然後可以使用 publint,arethetypeswrong,modern-guide-to-packaging-js-library 這些工具來檢查你的包是否符合規範。
npx publint
npx -p @arethetypeswrong/cli attw --pack .
我最終得出的配置如下:
{
"sideEffects": false,
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": ["./dist/*", "./dist/index.d.ts"]
}
},
"files": ["dist"]
}
保持依賴定義正確#
使用 knip 查找項目中未使用的文件、依賴項和導出。
npx knip
使用 taze 來手動更新依賴或者使用 renovatebot 來定時自動更新。
自動修復 lint#
為了保證 commit 的代碼符合代碼規範,可以使用 simple-git-hooks 來在 commit 之前進行檢查。
{
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
}
"scripts": {
"prepare": "simple-git-hooks",
}
}
不過這種方案存在的問題是,如果你的 ESLint 配置發生了變化,那 commit 的代碼依然可能存在需要修復的問題。所以我更傾向於在 CI 中進行檢查。使用 git-auto-commit-action 來自動修復並 apply 到當前分支。這樣還有一個好處是你不需要 require 其它貢獻者完全設置好正確的環境。
發版流程#
要使我們的包版本號 +1,大抵有以下幾個步驟:
- 進行發版前的檢查
- 更新版本號
- 發布到 npm
- commit && tag
- 寫這次更新的日誌,在 GitHub 上發布 release
如果每次都要手動做這些事情,那就太麻煩了,所以我們可以使用 release-it 來幫助我們自動化這些步驟。借助 release-it 的 hooks 功能和自定義插件,我們能夠方便的定義需要的發版流程。
release-it 對於 pnpm workspace 的支持幾乎為零,在 monorepo 發布多個包的情況下需要切換到其它方案,我寫了個插件提供簡單的支持。
在這個插件中我還按照自己的喜好自動決定下一個版本號,以及整合 bumpp 與 changelogithub。
我的 starter#
我將我收拾完的 starter 開源了,如果你和我的喜好一樣的話,可以基於它來改造自己的 starter。