- 作者:老汪软件技巧
- 发表时间:2024-11-05 04:01
- 浏览量:118
前言
最近,有被问到当多个项目具有很多公共组件和方法时,如何使用pnpm + monorepo的方式,把公共的东西都提取出来统一维护。大家可能多多少少都对这个有所了解,但是可能基本没怎么用过,也无从下手。下面我将从0-1手摸手带你使用pnpm快速搭建单一存储库来管理多个项目。
技术原理简介
pnpm内置了对单一存储库(也称为多包存储库、多项目存储库或单体存储库)的支持, 你可以创建一个workspace以将多个项目合并到一个仓库中。
项目目录结构设计
首先,我们可以先设想我们理想的项目结构,然后再根据这个项目结构去搭建我们的对项目开发环境。
// 项目目录结构
# pnpm-monorepo-demo
// 项目存放的目录
packages
// 项目a
- project-a
// 项目b
- project-b
// 项目公共的组件存放目录
components
// 项目公共的工具方法存放目录
utils
以上我们在根目录pnpm-monorepo-demo分别创建了packages、components、utils三个文件夹,分别用来保存项目、公共组件和公共方法。
项目创建
下面,我们在packages目录下打开命令行窗口运行以下命令,根据命令行指引,分别输入你的项目名和需要搭建的项目,在本文示例是通过vite分别创建两个project-a和project-b的vue + ts项目。如果想要搭建其他类型的项目也是同理。
pnpm create vite
创建完项目后,我们会得到以下指引让我们安装项目依赖后才能运行项目,我们先别着急安装。因为我们创建的project-a和project-b项目都是依赖相同的vue版本及开发环境,也是可以把公共依赖提取出来。
Done. Now run:
cd project-b
pnpm install
pnpm run dev
项目依赖共享
在根目录运行pnpm init初始化一个package.json文件,然后把项目中的dependencies和devDependencies依赖剪切出来,放到根目录的package.json文件当中,如剪切以下依赖项:
"dependencies": {
"vue": "^3.5.12"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.4",
"typescript": "~5.6.2",
"vite": "^5.4.10",
"vue-tsc": "^2.1.8"
}
在根目录命令行运行pnpm install安装项目所需依赖。安装完后,回到项目目录当中运行pnpm run start或pnpm start发现还是运行不起来呢!这是由于我们还没有搭建一个多项目的工作空间。
初始化多项目工作空间(Workspace)
在根目录下创建pnpm-workspace.yaml文件,并添加以下内容
packages:
- 'packages/*'
到此,我们就可以使packages目录下的project-a和project-b项目共享到根目录下的依赖项了。重新在project-a和project-b项目下打开命令行窗口,执行pnpm dev后,发现项目也能成功运行了!
公共组件包创建
首先,我们在pnpm-workspace.yaml文件中,把components文件目录加入到工作空间当中,在components目录下执行
`pnpm init`
初始化一个package.json文件,然后修改文件中的name名称为@pnpm-monorepo-demo/components,之后我们就可以在项目当中通过这个名称去安装公共组件依赖包。
安装工作空间当中的依赖
在project-a项目目录下打开命令行窗口,执行以下命令安装公共组件依赖
pnpm add @pnpm-monorepo-demo/components --workspace
以上@pnpm-monorepo-demo/components为components目录下的package.json文件中的name属性名称,表示从工作空间安装包,也就是我们在pnpm-workspace.yaml文件下配置的工作空间。
从上图中,我们可看到成功把公共组件添加到了project-a依赖当中。
使用方法:
在工作空间根目录components公共组件包下创建Panel/Panel.vue组件。
这里说一下我推荐的用法小技巧,由于公共组件的包名有些长,我们可以在当前项目根目录的components目录下创建一个index.ts文件,用来导出公共组件包中的所有组件。当然你也可以根据自己的习惯来。
/projetc-a/components/index.ts
import Panel from '@pnpm-monorepo-demo/components/Panel/Panel.vue'
export {
Panel
}
以上步骤完成后,我们就可以在页面中使用安装的公共组件包了!
App.vue
<template>
<Panel>Panel>
template>
公共方法包创建在utils目录下创建index.ts文件,并添加以下方法
export const add = (a: number, b: number) => {
return a + b
}
命令行执行以下命令
pnpm init
初始化一个package.json文件,修改name包名为@pnpm-monorepo-demo/utils,并把main属性改为index.ts,指定该文件为包的入口文件。
把utils文件添加到工作空间
pnpm-workspace.yaml
packages:
- 'packages/*'
- 'components/**'
- 'utils/**'
在项目中安装公共方法包
pnpm add @pnpm-monorepo-demo/utils --workspace
在页面中使用
还是使用之前使用公共组件的小技巧,在当前项目的创建src/urils/index.ts文件,用来导出所有公共方法
// 导出所有公共方法
export * from '@pnpm-monorepo-demo/utils'
App.vue
这样我们就可以更方便的使用公共方法了!
补充: 公共组件也可以像utils目录那样创建一个index.ts入口文件,用来统一导出所有组件。
打包运行
在对应项目目录下运行pnpm build打包命令单独打包即可。
推荐一个包live-server可以直接在dist打包输出文件目录下直接运行打包后的页面。
安装:
npm i live-server -g
在dist目录下打开命令行窗口,执行以下命令即可查看打包后的网页:
live-server
总结
其实pnpm + monorepo也不是什么黑魔法,主要的思想就是把每个可以独立出来的个体初始化一个pachage.json文件,当做一个包来引用,但是引用之前需要通过pnpm-workspace.yaml文件来配置当前工作空间包含哪些包,配置好对应包的目录后,就可以通过pnpm add 包名 --workspace来通过软连接的方式来引用这些包。