monorepo架构 pnpm + vue3 + typescript + husky + Commitlint + lint-staged

663 阅读3分钟

monorepo架构

  • 在一个项目结构,所有相关的工程形成子包进行管理
  • 技术栈统一
  • 项目间可共享,减少重复代码
  • 依赖管理,版本统一管理
  • 统一CI/CD流程

pnpm 优势

Unknown.svg

  • 软链接机制,节省磁盘空间
  • 安装速度快
  • 一句话概括中心化思想解决依赖重复安装问题

开始

新建工程monorepo-demo 在根目录下执行pnpm init,初始化package.json

pnpm init

package.json添加type

# package.json
{   ......
    "type": "module",
    ......
}

根目录下新建 pnpm-workspace.yaml

packages:  
    # 放你的项目 
    - 'apps/*'  
    # 公共组件,工具库
    - 'packages/*'   

pnpm官网

在apps目录下新建vue3项目main-app,勾选ESLint和Prettier

```js
pnpm create vue@latest  

当前目录结构

monorepo-demo
├── apps
│   ── main-app # 业务项目
│   ── other-app # 其他业务项目
├── packages
│   ── ui # 通用组件库
│   ── utils # 通用工具库
├── package.json
├── pnpm-workspace.yaml

写一个UI组件

在monorepo-demo/packages/ui目录下初始化package.json,并安装vue和typescript,版本尽量跟你业务工程里面版本号一致

    pnpm init
    pnpm add "vue@^3.5.13"
    pnpm add "typescript@~5.8.3" -D

修改package.json里面name,子包的名称

# package.json
{
    "name": "@wk/ui",
    ......
}

在monorepo-demo/packages/ui新建global.d.ts文件和tsconfig.json文件,配置ts环境,每个子包单独配置环境

global.d.ts

declare module '*.vue' {
    import { DefineComponent } from 'vue';
    const component: DefineComponent<{}, {}, any>;
    export default component;
  }

tsconfig.json

{
    "compilerOptions": {
      "outDir": "es",
      "target": "ES2015",
      "module": "ES2020",
      "moduleResolution": "node",
      "removeComments": true,
      "strict": true,
      "allowJs": true,
      "isolatedModules": true,
      "esModuleInterop": true,
      "jsx": "preserve",
      "jsxImportSource": "vue",
      "lib": ["ESNext", "DOM", "DOM.Iterable"],
      "skipLibCheck": true,
      "resolveJsonModule": true,
    },
    "include": [
      "components/**/*",
      "icon/**/*",
      "*.d.ts"
    ],
    "exclude": [
      "node_modules",
      "dist",
      "lib",
      "es",
      "json",
      "**/__tests__/**/*"
    ]
  }

ui子包的目录结构

ui
├── node_modules
├── src
│   ── components
│      ── layout
│          ── index.vue
│      ── index.ts
│   ── core
│   ── utils
├── global.d.ts
├── index.ts
├── package.json
├── tsconfig.json

ui/src/components/layout/index.vue

<template>
    <div style="color: cadetblue;font-size: 100px;">
      测试组件
    </div>
  </template>
  
  <script setup lang="ts">
  // 可以添加导航逻辑、inject、pinia 等
  </script>
  
  <style scoped>

  </style>

ui/src/components/index.ts

export { default as Layout } from "./layout/index.vue"

ui/index.ts

export * from "./src/components"

在apps/main-app中使用layout组件 安装组件

pnpm add @wk/ui --workspace

使用组件

    import { Layout } from "@wk/ui"

commitlint

官网

在项目根目录下安装,要加上-w,pnpm默认不允许在根目录下安装依赖

pnpm add -D @commitlint/cli @commitlint/config-conventional -w
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

在commitlint.config.js文件里自定义git提交规则

# commitlint.config.js
export default { 
    extends: ['@commitlint/config-conventional'],
    rules: {
        // 自定义规则
        'type-enum': [
          2,
          'always',
          ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert']
        ],
         // subject 大小写不做校验
         'subject-case': [0]
      }
};

Husky

官网

根目录安装

pnpm add --save-dev husky -w

初始化

    pnpm exec husky init

在.husky目录下新建commit-msg文件,和commitlint联系起来

# commit-msg
pnpm exec commitlint --edit $1

根目录下新建文件.gitmessage,设置提交格式提示,仅供参考

# .gitmessage
# 提交信息模板(遵循 Conventional Commits 规范)
# type(scope?): subject
# 格式:type(scope?): subject
# - type: 提交类型(必填)
# - scope: 影响范围(可选)
# - subject: 简短描述(必填,50字内)
#
# 支持的提交类型:
# - feat: 新功能 (示例:添加用户登录功能)
# - fix: 修复问题 (示例:修复按钮点击无效的问题)
# - docs: 文档变更 (示例:更新 README 文件)
# - style: 代码样式调整(不影响逻辑)(示例:格式化代码)
# - refactor: 代码重构(非功能变更)(示例:重构用户模块)
# - test: 测试相关 (示例:添加登录功能单元测试)
# - chore: 构建或工具变更 (示例:更新依赖)
# - revert: 回滚提交 (示例:回滚提交 abc1234)

根目录下执行

git config commit.template .gitmessage

lint-staged

github地址

在根目录下安装

pnpm add lint-staged -D -w

修改.husky/pre-commit文件,在提交之前做代码检查

# pre-commit
# 执行每个子包下面的lint-staged命令
pnpm -r run lint-staged

配置main-app子包 打开monorepo-demo/apps/main-app/package.json添加命令,并配置lint-staged

package.json
{
    ......
    "scripts": {
        ......
        "lint-staged": "lint-staged"
        ......
    }
    
  "lint-staged": {
    "*.{js,ts,jsx,tsx,vue}": ["pnpm lint", "pnpm format"],
    "*.{less,css}": ["pnpm format"]
  }
    ......
}

持续学习中。。。。。。