欢迎大家阅读鄙人在工作时搬的砖,下面是我在公司使用pnpm monorepo的一些实践,希望阅读完后对大家有所帮助。欢迎大家讨论~
概览
项目名为 @bnfe/utils-monorepo,是一个 Monorepo 项目,旨在整合公司所有的 npm 包到一个统一的项目中。该项目通过使用 Monorepo 结构管理多个子项目,每个子项目对应一个 npm 包,从而简化了包的管理、依赖关系和协作过程。同时,通过自定义的 CLI 工具,可以便捷地生成新的 npm 包和相应的文档。
代码地址
文档效果
使用效果
大家可以自行安装使用这些包 体验一下~
- 类型提示
- cjs esm 都支持
- 浏览器也可以用
- 无依赖
- tree shaking
- ...
目录结构
项目的包主要结构如下:
packages/common: 共用功能的npm包packages/node: 面向 Node.js 的npm包packages/h5: 面向 H5 平台的npm包packages/wx: 面向微信小程序的npm包packages/web: 面向 Web 平台的npm包
另外包含了: cli目录 docs目录 分别是该项目的cli工具 和 文档站点
.
├── README.md
├── cli
│ ├── package.json
│ └── src
│ ├── action
│ │ └── createAction.js
│ ├── consts
│ │ └── index.js
│ ├── index.js
│ ├── template
│ │ ├── template.txt
│ │ └── ts.txt
│ └── utils
│ └── index.js
├── commitlint.config.cjs
├── docs
│ ├── common
│ │ ├── README.md
│ │ ├── createQueryString.md
│ │ ├── deepClone.md
│ │ ├── distance.md
│ │ ├── filterPhone.md
│ │ ├── formatDate.md
│ │ ├── getTimestamp.md
│ │ ├── getType.md
│ │ ├── hidePhone.md
│ │ ├── isArray.md
│ │ ├── isEmpty.md
│ │ ├── isNumber.md
│ │ ├── random.md
│ │ ├── randomSort.md
│ │ └── uuid.md
│ ├── guide.md
│ ├── h5
│ │ └── README.md
│ ├── index.md
│ ├── install.md
│ ├── markdown-examples.md
│ ├── node
│ │ ├── README.md
│ │ ├── arrayToMap.md
│ │ ├── delay.md
│ │ ├── getAgeFromBirthday.md
│ │ ├── getRandomNumber.md
│ │ ├── md5.md
│ │ └── memoryUsage.md
│ ├── public
│ │ └── logo.png
│ ├── web
│ │ ├── README.md
│ │ ├── copyToClip.md
│ │ ├── createCookie.md
│ │ ├── deviceEnv.md
│ │ ├── getBrowerInfo.md
│ │ ├── getLocal.md
│ │ ├── getQuery.md
│ │ ├── getSession.md
│ │ ├── getUrlVal.md
│ │ ├── parseUrlValToJson.md
│ │ ├── readCookie.md
│ │ ├── removeCookie.md
│ │ ├── removeLocal.md
│ │ ├── removeSession.md
│ │ ├── setLocal.md
│ │ └── setSession.md
│ └── wx
│ └── README.md
├── package.json
├── packages
│ ├── common
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src
│ │ │ ├── __test__
│ │ │ ├── index.ts
│ │ │ └── utils
│ │ └── tsconfig.json
│ ├── debug
│ │ ├── debug-node-cjs-pkg
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── debug-node-mjs-pkg
│ │ ├── index.js
│ │ └── package.json
│ ├── h5
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ └── utils
│ │ └── tsconfig.json
│ ├── node
│ │ ├── CHANGELOG.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ └── utils
│ │ └── tsconfig.json
│ ├── web
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ └── utils
│ │ └── tsconfig.json
│ └── wx
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── babel.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── index.ts
│ │ └── utils
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── tsconfig.base.json
每个子项目对应一个 npm 包,通过统一的 Monorepo 管理和维护,提高了代码复用性和开发效率。
packages/debugs 目录并不是需要发布的包 而是用来调试的目录 当在一个包里 添加了一下内容/函数后 就可以来到这里进行发包前的测试和调试。
技术
在实现该项目的过程中,运用了这些技术:
- TypeScript
- Babel 插件
- Rollup 打包工具
- ESLint 和 Prettier码风格的统一。
- pnpm 包管理
- commamder 自定义 CLI 工具
- monorepo
- 规范开发 包
项目搭建过程
初始化项目
npm init -y
安装相关依赖
pnpm install typescript rollup @rollup/plugin-babel @babel/preset-typescript 等
配置pnpm workspace
这里配置了packages下所有需要发布的包
packages:
- 'packages/common'
- 'packages/node'
- 'packages/h5'
- 'packages/wx'
- 'packages/web'
eslint配置+preetier配置
需要先安装相关依赖
pnpm install eslint prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser
rollup配置
每个包下面都需要有这个rollup.config.js文件
import typescript from "rollup-plugin-typescript2";
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import { babel } from "@rollup/plugin-babel";
export default {
input: "src/index.ts",
output: [
{
file: "dist/common-utils.js",
format: "cjs"
},
{
file: "dist/common-utils.mjs",
format: "es"
},
{
file: "dist/common-utils.umd.js",
format: "umd",
name: "utilsCommon"
}
],
plugins: [
commonjs(),
typescript({
tsconfig: "./tsconfig.json",
useTsconfigDeclarationDir: true
}),
nodeResolve(),
babel({
exclude: "node_modules/**",
babelHelpers: "runtime",
extensions: [".js", ".ts"]
}),
json()
]
};
package.json脚本
包含了 打包 发布 测试 eslint 文档等一些脚本
"build": "pnpm run clearDist && pnpm -r run build",
"clearDist": "rimraf ./packages/**/dist/*",
"lint": "npx eslint . --fix",
"test": "vitest",
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs --outDir ./dist",
"docs:preview": "vitepress preview docs",
"deploy": "rimraf ./dist && npm run build && npm run docs:build && gh-pages -d ./dist --remote origin",
"preinstall": "npx only-allow pnpm",
"changeset": "changeset",
"changeset:version": "changeset version",
"pub": "pnpm run build && pnpm -r publish --access public --no-git-checks"
cli
用于快速开的cli
项目搭建完成之后 后续开发的整体流程
比如:在@bnfe/node-util包中新增一个求和函数及书写该函数的说明文档
-
新建求和函数 去到packages/node 目录下
- 在utils目录下新建一个以函数名为文件名的ts文件 (sum.ts)
- 书写求和函数相关代码 并导出该函数
-
新建求和函数说明文档 去到docs/node目录下
- 新建一个以函数名为文件名的md文件(sum.md)
- 书写该函数的使用文档
-
在该包的入口文件里导出求和函数
Tip : 1 , 2 步骤中的新建文件操作和3步骤 可以使用 cli 来完成
ucli create sum -d "这是一个求和函数"
Tip : 要使用 ucli 命令时 需要把该命令 link一下 (到项目cli 目录的终端 执行
npm link)
-
调试 求和函数 去到packages/debug下
- 找到该包对应的调试项目 或者 新建一个该包的调试项目(新建的时候 需要使用pnpm 安装一下要调试的包)
- 引入求和函数,执行一下
-
预览文档
- 预览之前 需要先打包一下 在根目录下 执行
npm run build - 然后执行
npm run doc:dev预览
- 预览之前 需要先打包一下 在根目录下 执行
-
发布包
- 可以自己手动去修改一下 package.json里面的 version字段 然后publish
- 也可以使用 changeset 命令 来更新version 然后publish
结语
上面之介绍了搭建过程中的一些粗略过程 大家如果感兴趣 可以去看代码仓库
有从0 -> 1的搭建commit哦