使用 monorepo 架构创建项目

pnpm workspace 实践

项目架构采用 pnpm workspace + changelog + husky

github 示例地址1 - Vue+Nest 全栈模版 github 示例地址2 - Vue+TS 前端模版

pnpm

项目初始化,修改车生成的 package.json 文件中的 private:true,防止根目录发布

sh 复制代码
pnpm init

根目录创建 pnpm-workspace.yaml 文件

配置 pnpm 的 monorepo 工作区,比如这里我们配置 blog 是博客主体,play 是测试用的,packages 下面又可以有主题包、组件包、工具包等等

这里注意一下,如果是多项目方式,根目录 package.json 中的 name 为项目名(看自己想定什么就设置一下)

而子项目中的 package.json 文件中的 name 就需要以 @ + 根目录 package.json 中的 name 名 + / + 子项目名

yaml 复制代码
packages:  
  - 'packages/*'
  - 'doc'

指定运行Node、pnpm 版本

json 复制代码
{
    "engines": {
        "node": ">=20",
        "pnpm": ">=8"
    }
}

接下来我们切换到 packages 目录中,创建子项目 比如我这里要创建 vitepress 项目

sh 复制代码
cd doc

pnpm dlx vitepress init

创建 vue 项目就使用

sh 复制代码
pnpm create vite

只允许使用 pnpm

如果不希望其他人使用 yarn、npm 等包管理器,只需要在 package.json 文件添加以下命令

json 复制代码
{
    "scripts": {
        "preinstall": "npx only-allow pnpm"
    }
}

只要有人使用其他包管理器安装依赖就会报错!

添加依赖

  • 全局依赖
sh 复制代码
pnpm add xxx -D -W
# or 
pnpm add xxx -Dw

-W:workspace-root 把依赖安装到全局 node_modules -D:开发依赖

依赖区别: dependencies:生产依赖 devDependencies:开发依赖 peerDependencies:宿主依赖(运行主依赖),指定当前模块包在使用需要安装的依赖

  • 局部依赖
sh 复制代码
# 路径在需要引入依赖的目录
pnpm add xxx -D

# 在根目录 @xxx/xxx 为子项目 name 名
pnpm add xxx -F @xxx/xxx

ESLint && Prettier

引入依赖

sh 复制代码
pnpm add eslint prettier -Dw

# 初始化 eslint 配置
pnpm eslint --init

# 其他依赖
pnpm add -Dw @typescript-eslint/parser eslint-plugin-vue @typescript-eslint/eslint-plugin

# 解决冲突
pnpm add eslint-config-prettier eslint-plugin-prettier -Dw

解决冲突

.eslintrc.cjs

js 复制代码
{
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-essential",
    // 将 prettier 放在最后面,让它的优先级比 eslint 低一点
    "plugin:prettier/recommended",
  ],
}

添加检查命令

json 复制代码
{
    "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx",
    "format": "prettier --write ./**/*.{vue,ts,tsx,js,jsx,css,less,scss,json,md}",
}

内部包的引用

husky + lint-staged 代码预检查

引入依赖

sh 复制代码
pnpm add husky lint-staged -Dw

添加脚本命令到 json 中

json 复制代码
{
  "prepare": "husky install"
}

运行一下命令,创建一个 pre-commit 钩子

sh 复制代码
#手动运行
pnpm prepare

#添加 pre-commit 钩子
npx husky add .husky/pre-commit "npx --no-install lint-staged"

pre-commit

sh 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# 这是自己加的
echo "--------- 代码预检查 ---------"

npx --no-install lint-staged

配置 lint-staged,在 package.json 中添加下面的配置信息

json 复制代码
//与 scripts 同一级
{
  "lint-staged": {
    "*.{js,vue,ts,jsx,tsx}": [
      "prettier --write",
      "eslint --fix"
    ],
    "*.{html,css,less,scss,md}": [
      "prettier --write"
    ]
  },
}

提交规范

引入依赖

sh 复制代码
pnpm add @commitlint/cli @commitlint/config-conventional cz-git -Dw

添加命令

json 复制代码
{
    "type":"module",
      "scripts": {
    "cz": "git cz",
  },
      "config": {
    "commitizen": {
      "path": "node_modules/cz-git"
    }
  },
}

我们用它来限制不符合规范的提交信息,根目录创建commitlint.config.js文件-如果后面报错就需要将文件改为 .cjs 同时还需修改一些内容

js 复制代码
// commitlint.config.js

/** @type {import('cz-git').UserConfig} */
export default {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "type-enum": [
      2,
      "always",
      [
        "feat",
        "fix",
        "docs",
        "style",
        "refactor",
        "test",
        "build",
        "chore",
        "perf",
        "ci",
        "revert",
      ],
    ],
    "type-case": [2, "always", "lower-case"],
    "type-empty": [2, "never"],
    "subject-full-stop": [2, "never", "."],
    "header-max-length": [2, "always", 100],
    "subject-case": [
      2,
      "never",
      ["sentence-case", "start-case", "pascal-case", "upper-case"],
    ],
  },
  prompt: {
    useEmoji: true,
    allowCustomIssuePrefix: true,
    allowEmptyIssuePrefix: true,
    confirmColorize: true,
    messages: {
      type: "选择你要提交的类型 :",
      scope: "选择一个提交范围(可选):",
      customScope: "请输入自定义的提交范围 :",
      subject: "填写简短精炼的变更描述 :\n",
      body: "填写更加详细的变更描述(可选)。使用 '|' 换行 :\n",
      breaking: "列举非兼容性重大的变更(可选)。使用 '|' 换行 :\n",
      footerPrefixesSelect: "选择关联issue前缀(可选):",
      customFooterPrefix: "输入自定义issue前缀 :",
      footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
      confirmCommit: "是否提交或修改commit ?",
    },
    types: [
      {
        value: "feat",
        emoji: "✨",
        name: "feat:     新增功能 | A new feature",
      },
      { value: "fix", name: "fix:      修复缺陷 | A bug fix" },
      {
        value: "docs",
        emoji: "📚",
        name: "docs:     文档更新 | Documentation only changes",
      },
      {
        value: "style",
        emoji: "💎",
        name: "style:    代码格式 | Changes that do not affect the meaning of the code",
      },
      {
        value: "refactor",
        emoji: "📦",
        name: "refactor: 代码重构 | A code change that neither fixes a bug nor adds a feature",
      },
      {
        value: "perf",
        emoji: "🚀",
        name: "perf:     性能提升 | A code change that improves performance",
      },
      {
        value: "test",
        emoji: "🚨",
        name: "test:     测试相关 | Adding missing tests or correcting existing tests",
      },
      {
        value: "build",
        emoji: "🛠",
        name: "build:    构建相关 | Changes that affect the build system or external dependencies",
      },
      {
        value: "ci",
        emoji: "⚙️",
        name: "ci:       持续集成 | Changes to our CI configuration files and scripts",
      },
      {
        value: "revert",
        emoji: "🗑",
        name: "revert:   回退代码 | Revert to a commit",
      },
      {
        value: "chore",
        emoji: "♻️",
        name: "chore:    其他修改 | Other changes that do not modify src or test files",
      },
    ],
  },
};

使用 husky 生成 commit-msg 文件,验证提交信息

sh 复制代码
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

commit-msg

sh 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# 自己加的
echo "--------- 执行commit-msg校验 ---------"

npx --no-install commitlint --edit $1

changeset

引入依赖并初始化

sh 复制代码
# -D 开发依赖
# -w 公共依赖
pnpm add -Dw @changesets/cli

# 初始化
pnpm changeset init

初始化后会在根目录下生成 .changeset 文件夹

其中 config.json 作为默认 changeset 配置文件

  • changelog: changelog 生成方式
  • commit: 不要让 changeset 在 publish 的时候帮我们做 git add
  • linked: 配置哪些包要共享版本
  • access: 公私有安全设定,内网建议 restricted ,开源使用 public
  • baseBranch: 项目主分支
  • updateInternalDependencies: 确保某包依赖的包发生 upgrade,该包也要发生 version upgrade 的衡量单位(量级)
  • ignore: 不需要变动 version 的包
  • ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH: 在每次 version 变动时一定无理由 patch 抬升依赖他的那些包的版本,防止陷入 major 优先的未更新问题

changeset 常用命令及说明

sh 复制代码
# 使用 changeset 进行记录版本修改
npx changeset add

# 使用 changeset version 提交版本修改
npx changeset version

# 使用 changeset publish 进行发包
npx changeset publish

版本号一般有三个部分,以.隔开,就像 X.Y.Z,其中

  • X:主版本号,不兼容的大改动,major
  • Y:次版本号,功能性的改动,minor
  • Z:修订版本号,问题修复,patch

changeset version 提交版本修改

.npmrc

pnpm 常用

.npmrc 复制代码
strict-peer-dependencies=false
shell-emulator=true
auto-install-peers=false
相关推荐
雾恋1 小时前
最近一年的感悟
前端·javascript·程序员
APItesterCris2 小时前
构建分布式京东商品数据采集系统:基于 API 的微服务实现方案
分布式·微服务·架构
A黄俊辉A2 小时前
axios+ts封装
开发语言·前端·javascript
小李小李不讲道理2 小时前
「Ant Design 组件库探索」四:Input组件
前端·javascript·react.js
程序员在线炒粉8元1份顺丰包邮送可乐2 小时前
Docker 部署生产环境可用的 MySQL 主从架构
mysql·docker·架构
连合机器人3 小时前
晨曦中的守望者:当科技为景区赋予温度
java·前端·科技
郑板桥303 小时前
tua-body-scroll-lock踩坑记录
前端·javascript
慢半拍iii4 小时前
JAVA Web —— A / 网页开发基础
前端
gnip4 小时前
pnpm 的 monorepo架构多包管理
前端·javascript
Angelyb5 小时前
微服务保护和分布式事务
java·微服务·架构