什么?使用monorepo管理公司的npm包

1,066 阅读4分钟

欢迎大家阅读鄙人在工作时搬的砖,下面是我在公司使用pnpm monorepo的一些实践,希望阅读完后对大家有所帮助。欢迎大家讨论~

概览

项目名为 @bnfe/utils-monorepo,是一个 Monorepo 项目,旨在整合公司所有的 npm 包到一个统一的项目中。该项目通过使用 Monorepo 结构管理多个子项目,每个子项目对应一个 npm 包,从而简化了包的管理、依赖关系和协作过程。同时,通过自定义的 CLI 工具,可以便捷地生成新的 npm 包和相应的文档。 代码地址

文档效果

image.png

image.png

image.png

image.png

使用效果

大家可以自行安装使用这些包 体验一下~

  • 类型提示
  • 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包中新增一个求和函数及书写该函数的说明文档

  1. 新建求和函数 去到packages/node 目录下

    1. 在utils目录下新建一个以函数名为文件名的ts文件 (sum.ts)
    2. 书写求和函数相关代码 并导出该函数
  2. 新建求和函数说明文档 去到docs/node目录下

    1. 新建一个以函数名为文件名的md文件(sum.md)
    2. 书写该函数的使用文档
  3. 在该包的入口文件里导出求和函数

Tip : 1 , 2 步骤中的新建文件操作和3步骤 可以使用 cli 来完成 ucli create sum -d "这是一个求和函数"

Tip : 要使用 ucli 命令时 需要把该命令 link一下 (到项目cli 目录的终端 执行 npm link

  1. 调试 求和函数 去到packages/debug下

    1. 找到该包对应的调试项目 或者 新建一个该包的调试项目(新建的时候 需要使用pnpm 安装一下要调试的包)
    2. 引入求和函数,执行一下

  1. 预览文档

    1. 预览之前 需要先打包一下 在根目录下 执行npm run build
    2. 然后执行npm run doc:dev预览
  2. 发布包

    1. 可以自己手动去修改一下 package.json里面的 version字段 然后publish
    2. 也可以使用 changeset 命令 来更新version 然后publish

结语

上面之介绍了搭建过程中的一些粗略过程 大家如果感兴趣 可以去看代码仓库

有从0 -> 1的搭建commit哦