@Dale-Lin
2022-03-09T19:50:38.000000Z
字数 2846
阅读 477
微前端
bootstrap
、mount
、unmount
三个声明周期钩子,以供主应用调用。
/** 只在微应用初始化时调用一次,重新进入时会调用 mount */
export const bootstrap = async () => {
console.log('bootstraping')
}
/** 每次进入都会调用 mount 钩子,通常在这里渲染应用 */
export const mount = async (props) => {
ReactDOM.render(<App />, props.container)
}
/** 每次切出/卸载会调用的方法,通常在这里卸载应用实例 */
export const unmount = async (props) => {
ReactDOM.unmountComponentAtNode(props.container)
}
/** 仅当使用 loadMicroApp 方式加载微应用时生效 */
export const update = async (props) => {
console.log('update props')
}
public-path.js
,以修改运行时 publicPath
处理微应用资源路径,需要在入口文件处引用:
// public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN
}
// index.ts
import './public-path'
// ......
output.library
和 output.libraryTarget
修改:
const pkgName = require('./package.json').name
let publicPath = '/' // dev
if (process.env === 'production') {
publicPath = 'https://cdn.example.com/${pkgname}/'
}
module.exports = {
output: {
publicPath: publicPath,
library: pkgName,
libraryTarget: 'window',
}
}
qiankun
:
$ yarn add qiankun
import { registerMicroApps, start } from 'qiankun'
// 注册微应用
// qiankun 会取 container 字段对应的 DOM 节点,传给微应用的 props.container
registerMicroApp([
{
name: 'sizeChartService',
entry: "https://cdn.example.com/app1/index.html",
container: '#container',
activeRule: '/sizeChart',
props: {
// 主应用传给微应用的数据
}
},
{
name: 'workflowService',
entry: "https://cdn.example.com/app2/index.html",
container: '#container',
activeRule: '/workflow'
}
], {
// 微应用暴露的生命周期钩子
beforeLoad: () => Promise<any>,
beforeMount: () => Promise<any>,
afterMount: () => Promise<any>,
beforeUnmount: () => Promise<any>,
afterUnmount: () => Promise<any>,
})
// 启动 qiankun,参数都可选
start({
// 是否开启沙箱模式
sandbox: false,
// 自定义 fetch 微应用资源的方法
fetch: (entry) {
// 请求资源带 timestamp 保证最新
return window.fetch(
`${entry}?timestamp=${Date.now()}`
)
}
})
activeRule 可以是一个接受 loction 对象的函数,在例如主应用是 hash 路由时, 可以通过一个函数返回 true/false 的方式来动态控制:
const getHashActiveRule = (activeHash) => (location) => location.hash.startsWith(activeHash)
registerMicroApp([
{
name: 'hashApp',
entry: 'https://cdn.example.com/hashApp/index.html',
container: '#container',
activeRule: getHashActiveRule('#/hashActivePrefix/hashApp')
}
])
如果微应用同时在 hash 路由和 history 路由的容器环境使用,内部其实需要根据容器路由模式判断使用
<BrowserRouter>
或<HashRouter>
。
loadMicroApp(microApp[, configuration])
加载微应用:
import { loadMicroApp } from 'qiankun'
// ...
const [microApp, setMicroApp] = useState(null)
const container = useRef(null)
useEffect({
if (container.current) {
const app = loadMicroApp({
// 必选,微应用的唯一名称
name: 'sizeChartService',
// 必选,微应用入口资源
entry: `https://cdn.example.com/microAppName/index.html?timestamp=${Date.now()}`,
// 必选,容器节点选择器或是 DOM 节点的 ref.current
container: containerRef.current,
// 可选,传给微应用的属性
props: {}
}, {
// configuration 同 qiankun.start
// ...
})
setMicroApp(app)
}
}, [container])
useEffect(() => () => {
// 组件卸载时需要手动卸载微应用
if (microApp) microApp.unmount()
}, [microApp])
如果微应用暴露了 update
生命周期钩子,还可以在主应用调用 microApp.update({ ...props })
更新。
在一个路由下需要渲染多个微应用时,就必须使用手动挂载方式