简单讲解怎么用pnpm搭建一个monorepo开源react项目(Vite 和 TypeScript)

背景

本人正在做一个开源截图、录屏和录像的跨平台桌面软件------pear-rec(梨子录像),本项目是基于ElectronReactVite搭建的,一开始是使用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 的一些主要特点:

  1. 快速安装速度:pnpm 使用了一种特殊的算法来高效地下载和安装包,因此安装速度比 npm 和 yarn 更快。在相同网络环境下,pnpm 的性能往往更好。
  2. 节省磁盘空间:相较于其他包管理器,pnpm 使用了一种共享文件夹存储机制,这意味着同一个版本的包只会被下载一次,可以在不同的项目之间共享。这样可以大大减少磁盘空间的占用。
  3. 支持本地安装:pnpm 允许在包的根目录下安装本地包,这样可以节省全局安装的时间和空间。本地安装的包不会被其他项目使用,只会在当前项目中使用。
  4. 支持 monorepo:pnpm 支持 monorepo(多仓库)项目,并可以通过符号链接的方式来链接各个包。这样可以使得不同的包可以互相引用,而不需要发布到 npm 上或手动维护自己的包管理系统。

总之,pnpm 是一个高效、节省空间的包管理器,适用于 Node.js 项目。它的安装速度快,可以节省磁盘空间,并支持 monorepo 项目。如果您担心磁盘空间占用或对快速安装有需求,那么 pnpm 可能是一个不错的选择。

vite

官网: cn.vitejs.dev/

Vite 是一个开发的前端构建工具,它被设计用来提供快速的开发体验。Vite 的特点是使用现代浏览器原生的 ES 模块(ESM)特性,以及利用了浏览器本地的模块系统来实现快速的开发和构建过程。

以下是 Vite 的一些主要特点:

  1. 快速的冷启动:Vite 通过在开发过程中利用浏览器本地的 ES 模块系统,避免了传统的打包和构建步骤,使得项目的冷启动速度非常快。这意味着在修改代码后,浏览器可以几乎立即更新。
  2. 按需编译:Vite 只会编译和解析你当前正在编辑的文件及其依赖,而不是整个项目。这使得开发过程更加高效,因为它只需要关注当前工作目录的代码。
  3. 原生的 ES 模块支持:Vite 使用标准的 ES 模块(ESM)来加载代码,这意味着你可以直接在代码中使用 import/export 语法,而不需要像在传统构建系统中一样使用其他模块规范(如 CommonJS 或 AMD)。
  4. 多语言支持:除了支持 Vue.js,Vite 还可以在同一个项目中处理多种不同的语言,例如 TypeScript、JavaScript、React、Preact、Lit、Svelte 等。
  5. 插件生态系统: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搭建一个vitemonorepo项目,可以按照以下步骤进行操作:

  1. 全局安装pnpm:打开终端,执行以下命令进行pnpm的全局安装:

    npm install -g pnpm

  2. 创建一个空的项目文件夹:在适当的文件夹位置,在终端中执行以下命令以创建一个名为my-monorepo的文件夹:

perl 复制代码
mkdir my-monorepo
  1. 初始化monorepo项目:进入创建的my-monorepo文件夹,并执行以下命令以初始化monorepo项目:
bash 复制代码
cd my-monorepo
pnpm init
  1. 新建一个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搭建ReactTypeScript项目

要使用vite创建一个ReactTypeScript项目,可以按照以下步骤进行操作:

  1. 创建一个React TypeScript项目:在适当的文件夹位置,在终端中执行以下命令以创建一个名为my-react-app的React TypeScript项目:
lua 复制代码
create-vite my-react-app --template react-ts

其中,my-react-app是你的项目的名称(比如我这里就是desktopwebdocsscreenshot),你可以根据需要自定义。

  1. 进入项目文件夹并安装依赖:在终端中执行以下命令以进入项目文件夹,并安装项目的依赖:
bash 复制代码
cd my-react-app
npm install
  1. 运行项目:在终端中执行以下命令以启动项目的开发服务器:
arduino 复制代码
npm run dev

然后,你就可以在浏览器中访问http://localhost:3000来查看你的React应用了。

这样,你就成功使用vite创建了一个ReactTypeScript项目。你可以在src文件夹中修改App.tsx文件来编写你的应用逻辑。

修改package

  1. 首先进入package
js 复制代码
cd ./package/web 
  1. 修改 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",
  1. 重新初始化
js 复制代码
pnpm init -y
  1. 修改 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(梨子录像)项目的依赖关系大概如下图:

  1. 添加依赖
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:^",
}
  1. 启动指令

修改/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 项目的有力工具。

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter8 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js
柳杉10 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化