使用 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
相关推荐
涔溪36 分钟前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun1 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇1 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
龙猫蓝图2 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
fakaifa2 小时前
CRMEB Pro版v3.1源码全开源+PC端+Uniapp前端+搭建教程
前端·小程序·uni-app·php·源码下载
夜色呦2 小时前
掌握ECMAScript模块化:构建高效JavaScript应用
前端·javascript·ecmascript