概述
可以使用 pnpm
的 monorepo 架构来共享公共组件、方法和第三方依赖,且效果非常好!
相比传统的 npm
和 yarn
,pnpm
在 monorepo 场景下提供了更好的包管理性能和依赖去重,特别适合微前端架构。
方案概述
pnpm
monorepo 主要依赖 workspace
机制,把多个子应用和公共包统一管理在一个单一的仓库 中。
主应用和子应用可以直接共享公共组件库、工具方法、第三方包,避免重复安装和版本冲突。
实现
1. 创建 pnpm
monorepo 项目
js
mkdir microfrontend-monorepo && cd microfrontend-monorepo
pnpm init
在 package.json
里启用 workspaces
:
js
{
"name": "microfrontend-monorepo",
"private": true,
"workspaces": ["packages/*", "apps/*"]
}
packages/
存放共享的公共组件库、工具库apps/
存放主应用和子应用
2. 添加共享的 packages
创建 shared-ui
(共享组件库)
js
cd packages/shared-ui
pnpm init
安装 React 组件依赖(如果是 Vue 则用 vue
)
js
pnpm add react react-dom
创建 index.tsx
js
// packages/shared-ui/src/Button.tsx
import React from "react";
export const Button = ({ text }: { text: string }) => {
return <button style={{ padding: "10px 20px", background: "blue", color: "white" }}>{text}</button>;
};
导出组件
js
// packages/shared-ui/index.ts
export * from "./src/Button";
添加 package.json
配置
js
{
"name": "@micro/shared-ui",
"version": "1.0.0",
"main": "index.ts",
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
创建 shared-utils
(共享工具库)
js
cd ../shared-utils
pnpm init
添加工具函数
js
// packages/shared-utils/index.ts
export const formatDate = (date: string) => new Date(date).toLocaleString();
配置 package.json
js
{
"name": "@micro/shared-utils",
"version": "1.0.0",
"main": "index.ts"
}
3. 创建 apps
目录(主应用和子应用)
js
mkdir -p apps/main-app apps/sub-app
配置主应用
js
cd apps/main-app
pnpm init
pnpm add react react-dom @micro/shared-ui @micro/shared-utils
在 App.tsx
里使用共享组件和方法
js
import React from "react";
import { Button } from "@micro/shared-ui";
import { formatDate } from "@micro/shared-utils";
const App = () => {
return (
<div>
<h1>主应用</h1>
<Button text="点击我" />
<p>当前时间:{formatDate(Date.now().toString())}</p>
</div>
);
};
export default App;
配置子应用
js
cd ../sub-app
pnpm init
pnpm add react react-dom @micro/shared-ui @micro/shared-utils
子应用 App.tsx
js
import React from "react";
import { Button } from "@micro/shared-ui";
const SubApp = () => {
return (
<div>
<h2>子应用</h2>
<Button text="我是子应用的按钮" />
</div>
);
};
export default SubApp;
4. 在 pnpm
monorepo 里安装依赖
回到项目根目录,运行:
js
pnpm install
pnpm
会自动去重依赖 ,所有 packages
和 apps
共享相同的 node_modules
,提升构建速度。
启动主应用和子应用
方式 1:独立运行(适合非微前端模式)
js
cd apps/main-app && pnpm start
cd apps/sub-app && pnpm start
这样主应用和子应用可以各自独立运行。
方式 2:微前端整合
使用 qiankun
微前端框架
主应用( main-app
)
js
import { registerMicroApps, start } from "qiankun";
registerMicroApps([
{
name: "sub-app",
entry: "//localhost:3001",
container: "#subapp-container",
activeRule: "/subapp",
},
]);
start();
子应用( sub-app
)
js
import { render } from "react-dom";
import SubApp from "./App";
export async function bootstrap() {
console.log("子应用 bootstrap");
}
export async function mount(props) {
console.log("子应用 mount", props);
render(<SubApp />, document.getElementById("root"));
}
export async function unmount() {
console.log("子应用 unmount");
}
优势
- 共享组件库 & 工具库 :所有子应用共用
@micro/shared-ui
和@micro/shared-utils
,代码复用率高。 - 自动依赖去重 :
pnpm
采用硬链接,不会重复安装 React、Ant Design 等第三方包。 - 独立开发 & 统一管理 :子应用可以独立开发 ,但也能享受 monorepo 的依赖管理。
- 微前端兼容性强 :可以配合
qiankun
、Module Federation
、Web Components
等方式实现微前端。
适合的场景
- 多子应用共享组件库、工具库
- 每个子应用可以独立运行,但也能合并成微前端
- 减少重复安装 React、Vue、Ant Design 等依赖