🧭 写在前面
随着业务增长,单体前端应用越来越"臃肿":
- 🪨 上线动辄 50MB,构建慢如蜗牛
- 🧩 多团队协作冲突频发,彼此依赖如"意大利面条"
- 🧨 某个团队上线导致全站崩溃
- 🪜 不同业务线需要差异化技术栈,难以统一
架构师必须提前"解耦"系统,为未来的业务增长打下模块化、独立化的技术基础。
本篇将围绕模块拆分、NPM 私有包管理、微前端架构落地展开完整实战方案。
🎯 一、什么是模块化架构设计?
将大型项目分解成多个独立、可发布、可被复用的子模块。
适用于以下场景:
- 多业务线、多人协作开发
- 可复用组件或工具模块
- 需支持差异化部署(A/B 实验、定制化页面)
🧱 二、模块拆分原则(RSC)
原则 | 含义 | 示例 |
---|---|---|
R(Reusable) | 高复用 | UI组件库、表单引擎、上传封装 |
S(Single Responsibility) | 单一职责 | user-auth、http-client、feature-toggle |
C(Composable) | 可组合 | form + validator + i18n |
示例结构:
bash
packages/
├── ui-kit/ # UI 组件
├── utils/ # 工具方法
├── api/ # 接口请求封装
├── hooks/ # 通用 hooks(usePagination)
├── form-engine/ # 动态表单模块
├── feature-x/ # 独立业务功能模块
apps/
├── main-app/
🧪 三、构建一个私有包系统(Monorepo 模式)
推荐工具选择:
类型 | 工具 |
---|---|
Monorepo 管理 | pnpm workspaces、Turborepo |
构建工具 | Vite、Rollup |
发布管理 | changesets |
本地包管理 | verdaccio(私有 npm 仓库) |
示例 pnpm-workspace.yaml
vbnet
packages:
- 'packages/*'
- 'apps/*'
每个包都具备独立 tsconfig + build 能力:
json
// packages/utils/tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"target": "ES2020",
"declaration": true,
"outDir": "dist"
},
"include": ["src"]
}
使用统一命令构建:
pnpm -r build
🧩 四、微前端架构实战(Module Federation)
原理简介:
Webpack 5 的 Module Federation
实现了多个子应用之间模块共享与动态加载,打破 bundle 边界。
🎯 主应用加载远程子模块(remoteEntry.js)并运行
子应用配置:
arduino
// webpack.config.js
new ModuleFederationPlugin({
name: 'appA',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button.vue',
},
})
主应用引入:
javascript
// bootstrap.js
import('appA/Button').then((module) => {
const Button = module.default
app.component('RemoteButton', Button)
})
适用于:
- 多业务团队并行开发
- 子应用独立发布、灰度控制
- 支持不同技术栈(Vue、React 可共存)
🔧 五、微前端调度系统设计
核心职责:
- 👀 注册各个子应用入口(remoteEntry)
- 🧭 动态加载子模块
- ✅ 权限判断是否允许展示
- 🚦 生命周期管理(load、mount、unmount)
路由接入示例:
scss
const apps = [ { name: 'user-center', url: '/user/remoteEntry.js', activePath: '/user' }, { name: 'settings', url: '/settings/remoteEntry.js', activePath: '/settings' }]
router.beforeEach((to) => {
const app = apps.find(a => to.path.startsWith(a.activePath))
if (app) {
loadRemoteApp(app)
}
})
🎛️ 六、组件隔离 + 样式沙箱处理
为了防止子应用污染主应用样式:
- ❌ 禁止全局样式、reset.css
- ✅ 使用 scoped + BEM 命名
- ✅ 推荐使用
shadow-dom
实现样式沙箱
ini
const shadowHost = document.createElement('div')
const shadowRoot = shadowHost.attachShadow({ mode: 'open' })
// 将子应用 DOM 挂载进去
shadowRoot.appendChild(appContent)
⚖️ 七、微前端架构的权衡
优势 | 代价 |
---|---|
独立部署、灰度上线更灵活 | 首屏加载慢(多个 remoteEntry) |
各团队技术栈解耦 | 增加配置复杂度 |
失败降级机制清晰 | 开发调试复杂 |
✅ 适合业务线独立度高的中大型项目,不适合初创项目。
🛠 八、构建脚手架自动生成模块模板
配合 plop
自动生成标准模块结构:
arduino
plop generate module
生成:
css
packages/
└── user-auth/
├── src/
├── index.ts
├── tsconfig.json
├── package.json
🧠 总结
架构师不是写一堆工具函数的人,而是定义团队开发范式和系统演进策略的人。
下一篇我们将深入探索架构师必备的权限体系与动态路由设计能力 :
👉 《前端权限体系设计:动态路由、按钮级权限与灰度控制》