pnpm 搭建 menorepo 工程

931 阅读1分钟

1、安装 pnpm

$ npm install -g pnpm

2、 创建子工程

  • 创建 abc 空文件夹,执行 pnpm init

  • 工程根目录下新建 packages 目录

  • 在 packages 目录下创建 pkg1 和 pkg2 两个工程

  • 分别执行 pnpm init 命令

  • 分别在 package.json 的中 name 字段分别叫做 @abc/pak1 和 @abc/pak2

  • 具体项目......

3、安装依赖规范

安装 "所有模块" 依赖

// 生产环境
$ pnpm install react -w

// 开发环境
$ pnpm install rollup -wD

安装 "所有模块" 依赖

// 使用 filter 关键字:package.json 的 name 字段
pnpm add axios --filter @qftjs/monorepo1


// `filter` 后面除了可以指定具体的包名,还可以跟着匹配规则来指定对匹配上规则的包进行操作
$ pnpm build --filter "./packages/**"

安装 "项目内模块" 依赖

$ pnpm install @qftjs/monorepo2 -r --filter @qftjs/monorepo1

只允许pnpm

{
  "scripts": {
    "preinstall": "npx only-allow pnpm"
  }
}

只允许pnpm

// 当前组件被引用时,依赖的包不被下载
"peerDependencies": {
    "@types/moment": "^2.13.0",
    "moment": "^2.30.1"
},
// 配合 peerDependencies 使用
"workspaces": {
    "packages": ["packages/*"], // 有效作用域
    "nohoist": ["**/moment", "**/@types/moment"] // 哪个包不被子组件使用
}

4、Release工作流:changesets(开发->提交变更->生成版本->发包)

安装

$ pnpm add -Dw @changesets/cli

初始化配置

$ pnpm changeset init

修改默认配置

  • 配置说明
    • 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 优先的未更新问题
{
  "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "linked": [["@qftjs/*"]],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": [],
  "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
      "onlyUpdatePeerDependentsWhenOutOfRange": true
  }
}

工程根目录下的 pacakge.json 的 scripts 中增加如下几条脚

{
  // 1. 编译阶段,生成构建产物
  "build": "pnpm --filter=@qftjs/* run build",
  
  // 2.  清理构建产物和 `node_modules`
  "clear": "rimraf 'packages/*/{lib,node_modules}' && rimraf node_modules",
  
  // 3. 执行 `changeset`,开始交互式填写变更集
  "changeset": "changeset"
  
  // 4. 执行 `changeset version`,修改发布包的版本
  "version-packages": "changeset version",
  
  // 5. 构建产物后发版本
  "release": "pnpm build && pnpm release:only", 
  // tag 参数:alpha - 测试版有bug、beta - 测试版本、rc - 代发候选版本
  "release:only": "changeset publish --registry=https://registry.npmjs.com/"
}

发布流程

# 进行了一些开发...

# 1、提交变更集
// 1.1 选择要发布的包
// 1.2 选择版本类型:
//   patch 更新小版本号,代表fix补丁
//   minor 更新中版本号,代表小功能改动
//   major 更新大版本号,代表功能大跨步升级
// 1.3 填写 Changelog
pnpm changeset


# 2、发布测试版本
#  2.1 选择版本
    pnpm changeset pre enter alpha   # 发布 alpha 版本
    pnpm changeset pre enter beta    # 发布 beta 版本
    pnpm changeset pre enter rc      # 发布 rc 版本
#  2.2 自动生成版本号
    pnpm version-packages
#  2.3 发包
    pnpm release
#  2.4 得到 1.0.0-beta.1
#  2.5 退出
    pnpm changeset pre exit
      
    
# 3、发布正式版本
pnpm changeset version
pnpm changeset publish

5、规范代码提交

安装依赖

$ pnpm install -wD commitizen cz-conventional-changelog

根目录下的 package.json 中增加一条脚本

"scripts": {
  "commit": "cz"
}

规范介绍

  • 一个标准化的 commit message 应该包含三个部分:Header、Body 和 Footer
    • Header:必填 - type(必需)、scope(可选)、subject(必需)
      • feat: 增加新功能
      • fix: 修复 bug
      • docs: 只改动了文档相关的内容
      • style: 不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
      • refactor: 代码重构时使用,既不是新增功能也不是代码的bud修复
      • perf: 提高性能的修改
      • test: 添加或修改测试代码
      • build: 构建工具或者外部依赖包的修改,比如更新依赖包的版本
      • ci: 持续集成的配置文件或者脚本的修改
      • chore: 杂项,其他不需要修改源代码或不需要修改测试代码的修改
      • revert: 撤销某次提交
    • Body 和 Footer:可选
    <type>(<scope>): <subject>
    // 空一行
    <body>
    // 空一行
    <footer>

6、结合 GitHub Actions 实现自动化版本修改和发布

自动修改版本

  • 结合 GitHub Actions 添加 version.yml 文件到 .github/workflows 目录
  • 当有代码合并到 release 分支时,将由 changeset 自动提交 PR 把子包的版本更新到正式版本
name: Version

on:
  push:
    branches:
      - release
env:
  CI: true
  PNPM_CACHE_FOLDER: .pnpm-store

jobs:
  version:
    name: Update Package Version
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - name: Setup Node.js 16
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install pnpm
        run: npm i pnpm@latest -g

      - name: Setup pnpm Config
        run: pnpm config set store-dir $PNPM_CACHE_FOLDER

      - name: Install Dependencies
        run: pnpm install

      - name: Create Release Pull Request
        uses: changesets/action@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

自动发布

  • 当 release 分支上的代码测试通过后,将合并到 main 分支上
  • 可结合 GitHub Actions 和 changesets publish 在 ci 流程上发布包到最新版本
name: Release

on:
  push:
    branches:
      - main
env:
  CI: true
  PNPM_CACHE_FOLDER: .pnpm-store

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - name: Setup Node.js 16
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install pnpm
        run: npm i pnpm@latest -g

      - name: Setup pnpm Config
        run: pnpm config set store-dir $PNPM_CACHE_FOLDER

      - name: Install Dependencies
        run: pnpm install

      - name: Build Packages
        run: pnpm run build

      - name: Publish Packages
        run: |
          pnpm config set "//registry.npmjs.org/:_authToken" "${NPM_TOKEN}"
          pnpm changeset publish
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}