micro-front-end
微前端的架构实践和思考Github
微前端到底是什么?
- 一种架构风格,将可独立交付的前端应用程序组成一个更大的整体。
- 多个团队开发的多个前端应用组合形成复杂平台类产品(感受就是一个SARS服务)
什么项目适合微前端架构?
- 拆分巨型应用,使应用变得更加可维护
- 兼容历史任务,实现增量开发
微前端架构的特点
- 独立部署
- 增量迁移
- 团队自治
- 松耦合代码
微前端架构方案
- 自由组织模式
- 基座模式
- 去中心模式 (新项目推荐选择这个,旧项目迁移困难的推荐前两个)
自由组织模式(自主研发)
- Iframe + postMessage
- Systemjs模块化解决方案
- 华为devCloud
不提供统一的基座,通过机制和规范,让用户只感知到一个产品; 多个SPA组成的MPA, 每个菜单就是一个SPA,Header 菜单就是一个工程化的APP,提供公共能力,维护每个SPA的生命周期。
基座模式
-
Single-spa 微前端框架
-
阿里的 qiankun
qiankun 是一个基于 single-spa 的微前端实现库
去中心模式 (没有固定的基座,所有的微应用都可以相互引用;也可以选择某个应用作为中心)
- webpack 5 ModuleFederationPlugin 模块联邦(微前端)
webpack 5 模块联邦示例
micro-react
- root微应用和user微应用可以相互引用
- 本示例 root微应用引入user微应用,user微应用也可以单独部署访问
使用
# 切换到user 根目录,安装依赖,并启动服务
yarn
yarn start
# 访问地址:http://localhost:9001
# 切换到root 根目录,安装依赖,并启动服务
yarn
yarn start
# 访问地址:http://localhost:9000
技术细节
// root/webpack.config.js
// 模块联邦
const { ModuleFederationPlugin } = require('webpack').container
new ModuleFederationPlugin({
name: 'roots',
remotes: {
microUser: 'microUser@http://localhost:9001/micro-user.js'
}
})
// user/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
new ModuleFederationPlugin({
// 对外提供打包后的文件名,导入时会使用
filename: 'micro-user.js',
// 微应用的名字,类似single-spa 的组织名
name: 'microUser',
// 具体导出
exposes: {
// 名字:具体某个组件
'./user':'./src/User.js',
'./goods':'./src/Goods.js'
}
})
// root/src/App.js
import React from 'react';
import User from './User'
const User2 = React.lazy(()=>import('microUser/user'))
const Goods = React.lazy(()=>import('microUser/goods'))
const App = () =>{
return (
<div>
<h1>Webpack 5 联邦模块 + React17 的微前端实践</h1>
<User/>
<div style={{border: '1px solid #ccc', marginTop: '24px', padding: '12px'}}>
<h3>来自其它微应用</h3>
<React.Suspense fallback="loading app">
<User2 />
<Goods />
</React.Suspense>
</div>
</div>
)
}
export default App
micro-vue3
- layout微应用和home微应用可以相互引用
- 本示例 layout微应用引入home微应用,home微应用也可以单独部署访问
使用
# 切换到home 根目录,安装依赖,并启动服务
yarn
yarn start
# 访问地址:http://localhost:9004
# 切换到layout 根目录,安装依赖,并启动服务
yarn
yarn start
# 访问地址:http://localhost:9003
技术细节
// home/webpack.config.js
// 模块联邦
const { ModuleFederationPlugin } = require('webpack').container
new ModuleFederationPlugin({
name: 'home',
filename: 'micro-home.js',
remotes: {},
exposes: {
"./Content": "./src/components/Content",
"./Button": "./src/components/Button"
}
}),
// layout/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
new ModuleFederationPlugin({
name: 'layout',
filename: 'micro-layout.js',
remotes: {
home: 'home@http://localhost:9004/micro-home.js'
},
exposes: {}
}),
// root/src/App.js
import React from 'react';
import User from './User'
const User2 = React.lazy(()=>import('microUser/user'))
const Goods = React.lazy(()=>import('microUser/goods'))
const App = () =>{
return (
<div>
<h1>Webpack 5 联邦模块 + React17 的微前端实践</h1>
<User/>
<div style={{border: '1px solid #ccc', marginTop: '24px', padding: '12px'}}>
<h3>来自其它微应用</h3>
<React.Suspense fallback="loading app">
<User2 />
<Goods />
</React.Suspense>
</div>
</div>
)
}
export default App
思考与展望
- 如何在 vue-cli 或者在 create-react-app 等cli 中使用webpack 5 的模块联邦?
- 旧项目如何通过qiankun(或者single-spa) 重构成为一个微前端的项目?