pnpm 构建 Monorepo workspace项目

pnpm 构建 Monorepo 项目

使用背景

因为公司要做的项目比较多,项目之间又会相互依赖。目前分为pc后台,pc商城,uniapp项目等等。所以为了代码的复用和代码的规范提交,决定引入pnpm来创建Monorepo项目。

Monorepo是什么呢(是多包单库管理)

Monorepo 简单的说,是指将公司的所有代码放到一个 Git / Mercurial / Subversion 的代码仓库中。对于很多没听说过这个概念的人而言,无异于天方夜谭。Git 仓库不应该是每个项目一个吗?对于很多用 monorepo 的公司,他们的 Git 仓库中不止有自己的代码,还包括了很多的依赖。基本上,只要把 monorepo 用 Git 拖下来,跑一下 ./scripts/install,就可以直接用 Buck / Bazel (在安装脚本中就装到了本地)编译仓库中的所有项目,并且提交修改(安装脚本配置好了代码提交环境,如果用的 Phabricator 的话,Gerrit 不用)

pnpm是什么呢

npm/yarn 采用了直接平铺的方式,而 pnpm 则是采用 .pnpm 隐藏目录隐藏真实的平铺结构,在使用链接(symbollink)的方式将真实安装的目录映射到 node_modules 下

为什么使用workspace呢

因为我们把项目剥离为业务组件层,通用api层,项目三层。项目引入通用api和业务组件相互依赖,所以我们搭建了内网npm。内网npm牵扯到了发包和版本号的问题,所以引入workspace 让项目内部进行引用类似这样

"devDependencies":{
  "**":"workspace:*"  
}

开始

第一步

我们在 packages 中新建以下几个目录。

├── packages
│   ├── ui-uniapp
│   ├── common-api

第二步

在根目录新建 pnpm-workspace.yaml,内容如下

packages:
  - 'packages/*'

第三步

npm init

生成package.json后

第四步

强制pnpm安装依赖

执行工程自身 preinstall
当前 npm 工程如果定义了 preinstall 钩子此时会被执行。

  "scripts": {
    "preinstall": "node preinstall.js",
  },

preinstall.js 中

if (!/pnpm/.test(process.env.npm_execpath || '')) {
  console.warn(
    `\u001b[33mThis repository requires using pnpm as the package manager ` +
      ` for scripts to work properly.\u001b[39m\n`
  )
  process.exit(1)
}

第五步

新增eslint stylelint prettier检测

  "scripts": {
    "preinstall": "node ./scripts/preinstall.js",
    "lint-staged": "lint-staged",
    "lint:eslint": "eslint --cache --max-warnings 0  \"packages/**/*.{vue,ts,tsx}\" --fix",
    "lint:prettier": "prettier --write  \"packages/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
    "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
    },
 "dependencies": {
    "stylelint": "^14.0.1",
    "stylelint-config-html": "^1.0.0",
    "stylelint-config-prettier": "^9.0.3",
    "stylelint-config-standard": "^23.0.0",
    "stylelint-order": "^5.0.0",
    "eslint": "^8.1.0",
    "@typescript-eslint/eslint-plugin": "^5.3.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-define-config": "^1.1.2",
    "eslint-plugin-jest": "^25.2.2",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-vue": "^8.0.3",
    "vue-eslint-parser": "^8.0.1",
    "prettier": "^2.5.1",
    "lint-staged": "^12.3.4",
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "prettier --write"
    ],
    "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
      "prettier --write--parser json"
    ],
    "package.json": [
      "prettier --write"
    ],
    "*.vue": [
      "prettier --write",
      "stylelint --fix"
    ],
    "*.{scss,less,styl,html}": [
      "stylelint --fix",
      "prettier --write"
    ],
    "*.md": [
      "prettier --write"
    ]
  }

第六步

增加git钩子
我的钩子命令是 pnpm run lint-staged

husky

npm install husky --save-dev
npm set-script postinstall "husky install"
npm run postinstall
npx husky add .husky/pre-commit " pnpm run lint-staged"
git add .husky/pre-commit

第七步

引入提交方式
安装依赖 commitizen和cz-conventional-changelog

 "scripts": {
    "commit": "cz"
  },
"config": {
    "commitizen": {
    "path": "cz-conventional-changelog"
    }
},
  • feat 增加新功能
  • fix 修复问题/BUG
  • upd 更新某功能
  • style 代码风格相关无影响运行结果的
  • perf 优化/性能提升
  • refactor 重构
  • revert 撤销修改
  • test 测试相关
  • docs 文档/注释
  • chore 依赖更新/脚手架配置修改等
  • workflow 工作流改进
  • ci 持续集成
  • mod 不确定分类的修改
  • wip 开发中
  • types 类型修改

你可能感兴趣的:(pnpm,workspace)