背景
本人正在做一个开源截图、录屏和录像的跨平台桌面软件------pear-rec(梨子录像),本项目是基于Electron
、React
和Vite
搭建的,一开始是使用vite-react-electron
脚手架快速搭建的,但是随着项目的越来越深入,单个项目的框架已经不能满足了,于是我就想到了monorepo
,本文就是用pnpm
搭建monorepo
项目的过程。
技术
- node.js(>=6.0)
- pnpm(>=8.0)
- vite
- react
- TypeScript
技术介绍
pnpm
官网: www.pnpm.cn/
pnpm
是一个快速、节省磁盘空间的包管理器,专门用于 Node.js
项目。它是 npm
(Node Package Manager)的替代品,但与 npm
不同的是,pnpm
通过共享包的存储机制来减少冗余,并且能够同时安装包的多个版本。
以下是 pnpm
的一些主要特点:
- 快速安装速度:pnpm 使用了一种特殊的算法来高效地下载和安装包,因此安装速度比 npm 和 yarn 更快。在相同网络环境下,pnpm 的性能往往更好。
- 节省磁盘空间:相较于其他包管理器,pnpm 使用了一种共享文件夹存储机制,这意味着同一个版本的包只会被下载一次,可以在不同的项目之间共享。这样可以大大减少磁盘空间的占用。
- 支持本地安装:pnpm 允许在包的根目录下安装本地包,这样可以节省全局安装的时间和空间。本地安装的包不会被其他项目使用,只会在当前项目中使用。
- 支持 monorepo:pnpm 支持 monorepo(多仓库)项目,并可以通过符号链接的方式来链接各个包。这样可以使得不同的包可以互相引用,而不需要发布到 npm 上或手动维护自己的包管理系统。
总之,pnpm
是一个高效、节省空间的包管理器,适用于 Node.js 项目。它的安装速度快,可以节省磁盘空间,并支持 monorepo
项目。如果您担心磁盘空间占用或对快速安装有需求,那么 pnpm 可能是一个不错的选择。
vite
官网: cn.vitejs.dev/
Vite
是一个开发的前端构建工具,它被设计用来提供快速的开发体验。Vite
的特点是使用现代浏览器原生的 ES 模块(ESM)特性,以及利用了浏览器本地的模块系统来实现快速的开发和构建过程。
以下是 Vite
的一些主要特点:
- 快速的冷启动:Vite 通过在开发过程中利用浏览器本地的 ES 模块系统,避免了传统的打包和构建步骤,使得项目的冷启动速度非常快。这意味着在修改代码后,浏览器可以几乎立即更新。
- 按需编译:Vite 只会编译和解析你当前正在编辑的文件及其依赖,而不是整个项目。这使得开发过程更加高效,因为它只需要关注当前工作目录的代码。
- 原生的 ES 模块支持:Vite 使用标准的 ES 模块(ESM)来加载代码,这意味着你可以直接在代码中使用 import/export 语法,而不需要像在传统构建系统中一样使用其他模块规范(如 CommonJS 或 AMD)。
- 多语言支持:除了支持 Vue.js,Vite 还可以在同一个项目中处理多种不同的语言,例如 TypeScript、JavaScript、React、Preact、Lit、Svelte 等。
- 插件生态系统:Vite 提供了一个插件机制,可以扩展其功能。许多常见的插件已经可用,并且社区也在不断增加新的插件,以满足不同项目的需求。
总之,Vite
是一个快速、基于现代浏览器原生 ES 模块的前端构建工具。它通过利用浏览器本地的模块系统来提供快速的开发体验,并提供了多语言支持和丰富的插件生态系统。如果你追求快速的开发速度和优化的开发体验,Vite 是一个非常值得尝试的工具。
创建项目
首先我们先构建出如下的项目结构
js
│ my-monorepo
├── package.json
├── packages
│ ├── desktop
│ │ ├── index.js
│ │ ├── package.json
│ │ └── test.test.js
│ ├── docs
│ │ ├── index.js
│ │ ├── package.json
│ │ └── test.test.js
│ └── screenshot
│ │ ├── index.js
│ │ ├── package.json
│ │ └── test.test.js
│ └── web
│ ├── index.js
│ ├── package.json
│ └── test.test.js
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
用pnpm
搭建monorepo
项目
要使用pnpm
搭建一个vite
的monorepo
项目,可以按照以下步骤进行操作:
-
全局安装pnpm:打开终端,执行以下命令进行pnpm的全局安装:
npm install -g pnpm
-
创建一个空的项目文件夹:在适当的文件夹位置,在终端中执行以下命令以创建一个名为
my-monorepo
的文件夹:
perl
mkdir my-monorepo
- 初始化
monorepo
项目:进入创建的my-monorepo
文件夹,并执行以下命令以初始化monorepo
项目:
bash
cd my-monorepo
pnpm init
- 新建一个
pnpm-workspace.yaml
文件,并写下以下代码:
pnpm-workspace.yaml
定义工作区的根目录,并使您能够在工作区中包含/排除目录。
js
# pnpm-workspace.yaml
packages:
# all packages in direct subdirs of packages/
- 'packages/*'
# all packages in subdirs of components/
- 'components/**'
# exclude packages that are inside test directories
- '!**/test/**'
用vite
搭建React
和TypeScript
项目
要使用vite
创建一个React
和TypeScript
项目,可以按照以下步骤进行操作:
- 创建一个React TypeScript项目:在适当的文件夹位置,在终端中执行以下命令以创建一个名为
my-react-app
的React TypeScript项目:
lua
create-vite my-react-app --template react-ts
其中,my-react-app
是你的项目的名称(比如我这里就是desktop 、web 、docs 、screenshot),你可以根据需要自定义。
- 进入项目文件夹并安装依赖:在终端中执行以下命令以进入项目文件夹,并安装项目的依赖:
bash
cd my-react-app
npm install
- 运行项目:在终端中执行以下命令以启动项目的开发服务器:
arduino
npm run dev
然后,你就可以在浏览器中访问http://localhost:3000
来查看你的React应用了。
这样,你就成功使用vite
创建了一个React
和TypeScript
项目。你可以在src
文件夹中修改App.tsx
文件来编写你的应用逻辑。
修改package
- 首先进入
package
js
cd ./package/web
- 修改 package.json
js
+ "name": "@pear-rec/web",
- "name": "my-react-app",
+ "type": "module",
+ "main": "./lib/web.umd.js",
+ "module": "./lib/web.es.js",
+ "types": "./lib/types/main.d.ts",
- 重新初始化
js
pnpm init -y
- 修改
vite.config.ts
javascript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { resolve, join } from "path";
import { visualizer } from "rollup-plugin-visualizer";
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
"@": join(__dirname, "src"),
},
},
plugins: [react(), visualizer()],
build: {
lib: {
entry: resolve(__dirname, "src/main.tsx"),
name: "web",
fileName: (format) => `web.${format}.js`,
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["react", "react-dom"],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
react: "React",
"react-dom": "react-dom",
},
},
},
outDir: "lib",
},
});
完整之后的目录,如下:
以上是我完成一个package
的过程,大家可以依次完成其他的package
。
项目配置 & 启动指令
pear-rec(梨子录像)项目的依赖关系大概如下图:
- 添加依赖
js
// 进入/packages/web
cd ./packages/web
pnpm add @pear-rec/screenshot --workspace
// 进入/packages/desktop
cd ../packages/desktop
pnpm add @pear-rec/web --workspace
// 进入/packages/docs
cd ../packages/docs
pnpm add @pear-rec/web --workspace
添加完成的/packages/web/package.json
文件,如下
js
"dependencies": {
+ "@pear-rec/screenshot": "workspace:^",
}
添加完成的/packages/desktop/package.json
文件,如下
js
"dependencies": {
+ "@pear-rec/web": "workspace:^",
}
添加完成的/packages/docs/package.json
文件,如下
js
"dependencies": {
+ "@pear-rec/web": "workspace:^",
}
- 启动指令
修改/package.json
文件
js
"scripts": {
"watch:packages": "pnpm run --filter=!@pear-rec/desktop --filter=!@pear-rec/docs watch",
"build:packages": "pnpm run --filter=!@pear-rec/desktop --filter=!@pear-rec/docs build",
"dev:desktop": "pnpm run -C packages/desktop dev",
"build:desktop": "pnpm run -C packages/desktop build",
"rebuild:desktop": "pnpm run -C packages/desktop rebuild",
"dev:web": "pnpm run -C packages/web dev",
"build:web": "pnpm run -C packages/web build",
"watch:web": "pnpm run -C packages/web watch",
"dev:docs": "pnpm run -C packages/docs dev",
"build:docs": "pnpm run -C packages/docs build",
"preview:docs": "pnpm run -C packages/docs preview",
"deploy:docs": "pnpm run -C packages/docs deploy",
"dev:screenshot": "pnpm run -C packages/screenshot dev",
"build:screenshot": "pnpm run -C packages/screenshot build",
"watch:screenshot": "pnpm run -C packages/screenshot watch"
},
修改/packages/**/package.json
文件
js
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"watch": "tsc && vite build -w",
},
最后我们使用pnpm run dev:web
就可以启动页面了!
总结
pnpm
是一个用于管理 monorepo
项目的工具。它是基于 pnpm
包管理器构建的,旨在解决 monorepo
项目中常见的问题。
pnpm
提供了一个集中的方式来安装、构建和管理多个子项目的依赖关系。它允许开发人员在不同的子项目之间共享依赖关系,并通过符号链接确保每个子项目都可以访问它们所需的依赖项。
pnpm
还支持并行安装依赖项,这可以显著提升安装速度。它还提供了命令行界面和配置文件,可以方便地管理项目的依赖关系、运行测试和构建任务等。
总结来说,pnpm
是一个灵活、高效的工具,可以帮助开发人员更轻松地管理 monorepo
项目中的依赖关系和构建任务。它简化了项目的结构,提高了开发效率,是构建大型 JavaScript
项目的有力工具。