这是我参与「第五届青训营」伴学笔记创作活动的第 11 天
一、 Monorepo 一个仓库管理多个项目
就是指在一个大的项目仓库中,管理多个模块/包(package),这种类型的项目大都在项目根目录下有一个 packages 文件夹,内面放置多个项目并进行管理,大概结构如下:
-- examples
-- packages
-- pkg1
--package.json
-- pkg2
--package.json
-- package.json
-- pnpm-workspace.yaml
-- README.md
目前很多我们熟知的项目都是采用这种模式,如Vant,ElementUI,Vue3等。打造一个Monorepo环境的工具有很多,如:lerna、pnpm、yarn 等等
参考文档:使用Vite和TypeScript带你从零打造一个属于自己的Vue3组件库 - 掘金 (juejin.cn)
优势:只需要通过管理根目录的 pnpm-workspace.yaml,实现当前仓库所有的项目都能引入 yaml 声明的所有组件
1. pnpm-workspace.yaml 文件
声明哪些文件可以被引用,哪些不能被引用
packages:
# packages 文件里面的 package.json 文件
- 'packages/*'
# 所有包在 packages 文件夹里面的文件
- 'packages/**'
# 排除测试目录中的包
- '!**/test/**'
官网参考:pnpm-workspace.yaml | pnpm中文文档 | pnpm中文网
注意:只要进行了排除的文件,配置脚本的时候 pnpm run --filter 会找不到对应的文件
解决:"publish": "cd ./packages/components/hview-ui & pnpm run release" cd 进那个目录在执行命令
1)包裹或者排除指定文件有什么用?
以当前目录为例:
-- examples 组件库测试
-- src
-- main.ts 文件主入口 # 4. import hp from "hview-plus" 里面引入了这个包
-- packages # 1. 在 yaml 里声明 packages 下面所有的组件都能被引入
-- components 组件开发
-- src
-- button.vue # 5. import hp from "@hview-plus/utils" 里面引入了这个包
-- package.json # 2. 包名 "hview-plus"
-- utils 存放公共函数文件夹
-- package.json # 3. 包名 "@hview-plus/utils"
只要我在 yaml 里面声明的内容,在该仓库的任何地方都可以进行引入,不过想使用指定的包的话,就需要手动在对应目录的 package.json 里面进行设置了
// examples/src/main.ts 文件
{
"dependencies": {
"hview-plus": "workspace:^1.0.0"
}
}
2)wrokspace 版本代表了什么?
workspace:^1.0.0 表示引入的 hview-plus 包为:1.0.0 版本
// packages/components/package.json 设置版本
{
"name": "hview-plus"
"version": "1.0.0",
}
注意:既然引入的包是 1.0.0 版本,那么对应的 hview-plus 包 就必须设置为 1.0.0 版本
3)如果仓库出现了多个相同的包名怎么办?
最好的解决办法就是在 yaml 里面对你不想引入的包名进行排除:
packages:
- "packages/**"
- "examples"
- "site"
- "!packages/components/transitpkg"
- "!packages/components/hview-ui"
比如我这里的 transitpkg、hview-ui 和 components 他们三个的 package.json 是同名的,我只想让 examples 项目里面引用到 components 的内容即可,就需要对 packages 里面的 transitpkg 和 hview-ui 进行排除即可
2. 依赖安装
在项目根目录安装依赖包 ppnpm i xxx -w 如果是要添加开发依赖 pnpm i xxx -D -w
3. 详细说一下 package.json 每个字段的功能
{
"name": "hview-ui", // 包名:在仓库内别人 import 的包名是啥
"version": "1.0.0", // 版本:引入的包的版本的 workspace 和这里要一致
"description": "", // 描述:npm 上面对这个包的描述信息
"main": "index.js", // CommonJS:使用这个包会从那个文件导出
"module": "index.mjs", // ESModule:使用这个包会从那个文件导出
"typings": "hview-ui/lib/index.d.ts", // 当前包的声明文件,很重要使用ts的话必须要搞,还要在包内写上 xx.d.ts 声明文件
"scripts": { // 脚本命令
"dev": "pnpm run --filter ./examples dev", // --filter 回去找目标目录下 package.json 的 dev 脚本命令
"build": "gulp -f packages/components/script/build/gulpfile.ts",
"publish": "cd ./packages/components/hview-ui & pnpm run release", // --filter找不到的话,就去 cd 进去在执行
"publish:gulp": "pnpm run build & gulp -f packages/components/script/publish/gulpfile.ts", // 先执行 build 在执行 gulp
"docs:dev": "pnpm run --filter ./site docs:dev",
},
"devDependencies": { // 开发环境依赖包:打包时候不会打包进 node_modules
"@release-it/conventional-changelog": "^5.1.1",
},
"dependencies": { // 生产环境依赖包:打包的时候会打包进 node_modules
"vue-i18n": "^9.2.2"
},
"files": [ // 将哪些文件推送到 npm 包里面
"hview-ui/es",
"hview-ui/lib"
],
"keywords": [], // npm 包的关键字信息
"author": "", // 作者信息
"license": "MIT", // 遵循的哪个开源协议
}
4. 依赖包扩展 TS 声明
declare module "@vue/runtime-core" {
export interface GlobalComponents { // 声明"@vue/runtime-core"里面会导出一个 GlobalComponents 类型
HButton: typeof import("hview-plus").Button;
}
}
export {};
/// <reference types="vite/client" />
declare module "*.vue" {
import { DefineComponent } from "vue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>;
export default component; // 声明"*.vue"都会默认暴露 component 类型
}
二、规范团队代码
参考文档:
- 前端基于husky通过eslint检测提交代码 - 掘金 (juejin.cn)
- vue3+ts+vite项目中使用eslint+prettier+stylelint+husky指南 - 掘金 (juejin.cn)
- 如何在Vue3项目中集成ESLint+Prettier+Stylelint+Husky? - 掘金 (juejin.cn)
1. Eslint 和 Prettier 统一代码风格和质量校验
参考文档:
1)VScode 插件和设置
A. 插件安装
B. VScode 设置
打开vscode 配置文件 setting.json
快捷键:ctrl + p 然后输入 > 进入命令搜索模式,再输入: Settings(JSON),选择用户设置
1、设置代码在保存的时候自动格式化
{
"editor.formatOnSave": true
}
2、设置 .js .ts .jsx .tsx .less .css .json 格式的文件都采用 prettier-vscode 插件进行格式化
{
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[javascript|react]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescript|react]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[less]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
}
3、配置 prettier 插件读取项目中哪个配置文件,默认是根目录下的 .prettierrc 文件,如果你的项目下不是这个文件就需要修改为你的配置文件,比如很多项目为 .prettierrc.js 或者 .prettierrc.ts
这条内容不需要加在 vscode 里面了,添加在项目根目录 .vscode / settings.json 文件里面
{
"prettier.configPath": ".prettierrc.json"
}
至此配置过程就完成了,现在来试试效果,遇到黄色的警告 Ctrl+S 保存格式化代码即可
还需要注意用 vscode 打开跟目录的项目,不要用 vscode 打开里面某个项目(例如packages),格式化的时候它会去找 .prettierrc.json 文件,别的目录没有的话不会进行格式化
遇到无法格式化的文件,在文件代码区域 - 右键使用..格式化文档 - 选择 Prettier 即可
2)Eslint 配置
官网参考:规则 - ESLint - 可插拔的JavaScript Linter
使用配置:最全的Eslint配置模板,从此统一团队的编程习惯
3)Prettier 配置
官网参考:配置 Prettier 的一些参数
使用配置:最全的Eslint配置模板,从此统一团队的编程习惯
2. husky、lint-staged 和 commitlint 限制 git 提交
1)自动配置 husky
自行选择自己的包的类型,进行输入命令
yarn add husky --dev # must install
npx husky-init install # npm
npx husky-init # Yarn 1
yarn dlx husky-init # Yarn 2+
pnpm dlx husky-init # pnpm
它将设置 husky,修改package.json并创建一个pre-commit您可以编辑的示例挂钩。默认情况下,它将npm test在您提交时运行,例如:
把示例 npm test 修改成 pnpm run lint-staged 或者 您自己定义的命令
在 package.json中添加 lint-staged 命令
{
"scripts": {
"lint-staged": "lint-staged --allow-empty",
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
"prepare": "husky install"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx,.vue}": "pnpm run lint-staged:js",
"**/*.{js,jsx,tsx,ts,less,md,json,.vue}": [
"prettier --write"
]
}
}
当 commit 执行的时候,我回去运行 npm rest 脚本命令
2)lint-staged 配置
当我们执行git commit的时候就会先执行npm run lint,只有lint通过后才会提交,但是这样每次提交都要全量检查文件有点太费时,如果我们想让它只检查提交的文件可以使用lint-staged这个插件:
pnpm i -D lint-staged
然后在package.json中配置
{
"lint-staged": {
"**/*.{js,jsx,ts,tsx,.vue}": "pnpm run lint-staged:js",
"**/*.{js,jsx,tsx,ts,less,md,json,.vue}": [
"prettier --write"
]
}
}
然后将 pre-commit 中的 npm run lint 修改为npx --no -- lint-staged即可
如果想指定某个文件夹目录下的内容进行校验的话,通过这样设置:
{
"lint-staged": {
"packages/*.{js,jsx,ts,tsx,.vue}": "pnpm run lint-staged:js",
"packages/*.{js,jsx,tsx,ts,less,md,json,.vue}": [
"prettier --write"
]
}
}
只对这些指定的文件进行校验和格式化
3)commit 提交信息规范
除了代码规范以外,代码的提交信息我们也需要进行一个规范,这里我们可以直接使用commitlint以及它的工具库
pnpm i commitlint @commitlint/cli @commitlint/config-conventional -D
新建.commitlintrc.cjs
module.exports = {
extends: ["@commitlint/config-conventional"]
};
@commitlint/config-conventional规定的 commit 信息一般由两个部分: type 和 subject 组成,结构为: , 如新增功能feat: add fun
type 如下
- build 影响项目构建或依赖项修改
- chore 其他修改
- ci 持续集成相关文件修改
- docs 文档修改
- feat 添加新功能
- fix 修复 bug
- perf 更改代码,以提高性能
- refactor 代码重构
- revert 恢复上一次提交
- style 代码格式修改
- test 测试用例新增、修改
将commitlint集成到husky中
npx husky add .husky/commit-msg "npx --no-install commitlint -e $HUSKY_GIT_PARAMS"
复制代码
然后.husky下就多了一个commit-msg文件
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint -e
我们试着提交一个不符合规范的信息就会发现控制台拦截了我们的commit