架子包括:
- 定义项目结构(Mono-repo)
- 定义开发规范(lint、代码风格、commit、tsc)
- 选择打包工具(rollup)
项目结构
Multi-repo VS. Mono-repo
- Multi-repo:每个项目有自己独立的仓库,逻辑清晰,相对独立,难以共享代码
- Mono-repo:一个仓库中包含多个相关联的项目,可以很方便的共享代码,协同管理不同项目的生命周期,但会有更高的架构难度和操作复杂度
一般 Mono-repo 的目录如下所示,在 packages
存放多个子项目,并且每个子项目都有自己的 package.json
:
├── packages
| ├── pkg1
| | ├── package.json
| ├── pkg2
| | ├── package.json
├── package.json
参考资料:现代前端工程为什么越来越离不开 Monorepo?
我们要实现的 React 分为很多包,如:
react
、react-dom
、react-reconciler
等,它们关系密切,需要互相调用,所以采用 Mono-repo 组织项目。
Mono-repo 技术选型
简单工具:
专业工具:
pnpm 相比其他打包工具的优势:
- 依赖安装快(软链接)
- 更规范(处理幽灵依赖问题)
参考资料:pnpm 是凭什么对 npm 和 yarn 降维打击的?
我们采用 pnpm 作为包管理工具,Mono-repo 落地选用 pnpm workspace
初始化项目
git init # 初始化 git 仓库
npm install -g pnpm
pnpm init # 创建 package.json
.gitignore
:
.DS_Store
node_modules
dist
# pnpm-workspace.yaml
packages:
- 'packages/*'
定义开发规范
lint 工具:ESLint
安装:pnpm i -D -w eslint
初始化:
pnpm exec eslint --init # 或:npx eslint --init
? How would you like to use ESLint?
# To check syntax and find problems
# ESLint 只做检查语法 + 发现问题,代码风格交给 Prettier
? What type of modules does your project use?
# JavaScript modules (import/export)
? Which framework does your project use?
# None of these
? Does your project use TypeScript?
# Yes
? Where does your code run?
# Browser ✅
# Node ✅
? Would you like to install them now?
# No
# 我们自己安装,因为它安装不加 -w,会报错
pnpm i -D -w globals @eslint/js typescript-eslint
生成的 eslint.config.mjs
:
import globals from 'globals'
import pluginJs from '@eslint/js'
import tsEslint from 'typescript-eslint'
export default [
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
pluginJs.configs.recommended,
...tsEslint.configs.recommended,
]
为 lint
增加对应的执行脚本:
"lint": "eslint --fix --quiet ./packages"
代码风格:Prettier
安装:pnpm i -D -w prettier
新建配置文件 .prettierrc.json
:
{
"semi": false,
"singleQuote": true,
"printWidth": 120,
"useTabs": false,
"tabWidth": 2,
"bracketSpacing": true,
"trailingComma": "all",
"arrowParens": "avoid"
}
ESLint 9 不需要解决与 Prettier 冲突的问题了
eslint-config-prettier
:关闭所有与 Prettier 冲突的 ESLint 规则eslint-plugin-prettier
:将 Prettier 作为 ESLint 规则来运行,这样在运行 ESLint 时也会运行 Prettierpnpm i eslint-config-prettier eslint-plugin-prettier -D -w
为 style
增加对应的执行脚本:
"format": "prettier --write ./packages"
安装 Prettier 与 ESLint 的 VSCode 插件,并设置为保存后自动执行:Format On Save
commit 规范检查:CommitLint
通过 commitlint 对 git commit
提交信息进行检查,安装必要的库:
pnpm i -D -w @commitlint/cli @commitlint/config-conventional
新建配置文件 commitlint.config.mjs
:
export default {
extends: ['@commitlint/config-conventional'],
}
conventional 规范集意义:
type(scope?): subject
# 类型(范围): 主题
# 范围是可选的,支持多个范围,用 "/"、"\"、"," 分割
type
值:
feat
:添加新功能fix
:修复 Bugdocs
:文档的修改style
:不影响代码含义的更改refactor
:代码重构perf
:性能方面的优化test
:添加缺失的测试或更正现有测试build
:影响构建系统或外部依赖项的更改ci
:更改 CI 配置文件和脚本chore
:一些不影响功能的更改(杂项)revert
:恢复之前的提交
提交时自动运行
安装:pnpm i -D -w husky lint-staged
- husky:用于拦截
git commit
命令 - lint-staged:只对暂存区代码进行检查
初始化 husky:
pnpm exec husky init
.husky/pre-commit
:
pnpm exec lint-staged
.husky/commit-msg
:
npx --no-install commitlint --edit "$1"
package.json
:
{
"scripts": {
"prepare": "husky",
"lint": "eslint --fix --quiet ./packages",
"format": "prettier --write ./packages"
},
"lint-staged": {
"./packages/**/*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix --quiet"
]
},
}
打包工具
比较不同打包工具的区别,我们要开发的项目的特点:
- 是库,而不是业务项目
- 希望工具尽可能简洁、打包产物可读性高
- 原生支持 ESM
所以选择 rollup,安装:pnpm i -D -w rollup