从零开始使用monorepo搭建组件库
Monorepo
第一步:创建npmjs组织
istrcnMonorepo 和 Multirepo
单一仓库(Monorepo)架构,可以理解为:利用单一仓库来管理多个packages的一种策略或手段;与其相对的是多仓库(Multirepo)架构
- Monorepo 目录中除了会有公共的
package.json依赖以外,在每个sub-package子包下面,也会有其特有的package.json依赖。
兄弟模块之间可以通过模块 package.json 定义的 name 相互引用,保证模块之间的独立性
- Multirepo 更倾向与在项目制中,将一个个项目使用不同的仓库进行隔离,每一个项目下使用独有的
package.json来管理依赖
Monorepo 项目搭建
安装包管理工具
初始化项目
创建一个新的项目目录
istr-node-package,根目录运行pnpm init创建package.json文件然后根目录新建一个文件夹
packages,用于存储子包2.1. 新建
packages/istr-shared( 共享包 ),用于存放多个项目或组件之间共享的代码 。运行pnpm init创建package.json文件,修改package.json的 name 为"@istr/shared";修改package.json的 main 入口文件路径字段为`"src/index.js"2.2. 新建
packages/istr-ui( 公共组件包 ),即UI组件库。运行pnpm init创建package.json文件,修改package.json的 name 为"@istr/ui";修改package.json的 main 入口文件路径字段为`"src/index.js"配置workspace
根目录新建一个
pnpm-workspace.yaml,将 packages 下所有的目录都作为包进行管理yamlpackages: # all packages in direct subdirs of packages/ - 'packages/*'
pnpm-monorepo 最终项目结构
pnpm-monorepo/
├── packages/
│ ├── libc-shared/
│ ├── libc-ui/
│ ├── vue-dome1/
│ └── vue-dome2/
├── package.json
└── pnpm-workspace.yaml子包共享
此时,pnpm-workspace.yaml工作空间下的每个子包都可以共享我们的公共依赖了。还有个问题是,兄弟模块之间如何共享呢? 之前我们说过,子包之间可以通过 package.json 定义的 name 相互引用,一起看下两个实际场景
- 如何把子包 libc-shared 共享出去?
用--workspace参数去安装共享子包,会去 workspace工作空间中找依赖项并安装
sql
体验AI代码助手
代码解读
复制代码pnpm install @libc/shared --workspace -wpackage.json 中就会自动添加如下依赖,"workspace:" 只会解析本地 workspace 包含的 package
x"dependencies": {
"@libc/shared": "workspace:^"
}此时,vue 项目就可以使用公共包 libc-shared 里的方法,import 引入即可
import { isObject } from '@libc/shared'- 如何把子包 libc-ui 共享出去?
重复一下上面的步骤,然后我们去引用一个 button组件,发现报错了Failed to resolve import "./base" from "../libc-ui/src/components/typography/title.vue". Does the file exist? vite.config.js 中添加 extensions 即可解决,配置一下省略的扩展名列表
resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
}虽然 button 组件引用成功了,但是发现没有任何样式效果。在libc-ui/src/index.js 文件中导入一下样式文件就行了
import "./styles/index.less";公共依赖
全局安装公共依赖 lodash。需要加-w(在工作空间的根目录中启动 pnpm)
$ pnpm install lodash -w
$ pnpm add rimraf -D -w这样,vue-dom1 和 vue-dom2 这两个 vue项目就都可以使用 lodash 库了
局部依赖
如果只有 vue-dom1 项目用到了 lodash,我们也可以安装到vue-dom1 项目内部,不作为公共依赖项,有两种方法可以实现
- cd 到
src/packages/vue-dom1目录下,直接安装
$ pnpm install lodash- 在任意目录下,使用
--filter参数进行安装
$ pnpm install lodash --filter vue-demo1shared包
typescript封装js帮助类
$ pnpm install vite -w
$ pnpm install vite-plugin-dts -D -w修改 package.json
调整 package.json 以支持组件库发布:
{
"name": "xxh-v3-tempcom",
// 是否为私人组件,这里需要修改为 fase
"private": false,
// 版本,每次提交之前都需要修改,否则提交失败
"version": "1.0.1",
// 类型必须为 module
"type": "module",
// 该组件默认指向路径
"main": "dist/xxh-v3-tempcom.js",
// 当以类似 import 方式引入时的默认目标, 如: import xxx from "xxh-v3-tempcom"
"module": "dist/xxh-v3-tempcom.umd.cjs",
// 类型定义文件,这个必须要写,要不然也无法自动提示
"types": "dist/index.d.ts",
// 当运行 npm publish 时,需要提交到 npm 的文件
"files": [
"package.json",
"README.md",
"dist"
],
"author": "xxh-h",
"license": "MIT",
"description": "用于测试打包提示的项目",
// 用于在 npm 中搜索的关键字
"keywords": [
"vite",
"vue3",
"typescript",
"demo"
],
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.5.13"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.7.0",
"typescript": "~5.7.2",
"vite": "^6.1.0",
"vite-plugin-dts": "^4.5.0",
"vue-tsc": "^2.2.0"
}
}{
"main": "./dist/index.cjs", // CommonJS 格式的入口文件
"module": "./dist/index.esm.js", // ES Modules 格式的入口文件
"exports": {
"import": "./dist/index.esm.js", // 用于现代工具链(如 Vite)
"require": "./dist/index.cjs" // 用于 CommonJS 环境
},
"types": "./dist/index.d.ts" // TypeScript 类型定义文件
}https://cn.vitejs.dev/guide/build.html#library-mode
发布
pnpm login --registry https://registry.npmjs.org
pnpm publish --registry https://registry.npmjs.org
pnpm -r publish --access public --no-git-checks-r或--recursive:对所有子包执行publish。--access public:
- 如果发布的包是公开的(默认是私有包),需要显式指定为
public。 - 私有作用域包(如
@scope/package)默认是私有的,必须设置--access public才能发布为公开包。
- 如果发布的包是公开的(默认是私有包),需要显式指定为
高级
统一依赖版本
使用pnpm catelogs,文档: https://www.pnpm.cn/catalogs
丰富项目
- .npmrc
- .editorconfig
将父级目录定义成 "private": true,避免被publish发布
遇到的问题
发布失败
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/@istrcn%2fshared - Not found
npm error 404
npm error 404 '@istr/shared@1.0.0' is not in this registry.
npm error 404
npm error 404 Note that you can also install from a
npm error 404 tarball, folder, http url, or git url.原因: 没有在npmjs中注册私有scope