简单讲解怎么用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 项目的有力工具。

相关推荐
Martin -Tang28 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发29 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
老码沉思录1 小时前
React Native 全栈开发实战班 - 第四部分:用户界面进阶之动画效果实现
react native·react.js·ui
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习