需求
最近在做一个代码平台,其中一个核心需求是可以使用React和Vue为平台开发组件
调研
参考了鲁班H5, 阿里的lowcode-engine,百度的amis 都只能使用平台开发的框架作为基础去开发组件,鲁班用Vue,阿里,百度的用React。最后搜索看到qiankun微前端框架,理论是符合需求,但是qiankun是应用级的,基于路由加载,不能直接套用。qiankun底层依赖 single-spa,single-spa底层依赖Systemjs加载应用,应用也是一个组件,所以将组件打包成systemjs格式,然后在平台上使加systemjs加载理论是上可行,而且webpack和rollup都支持输出systemjs
开干
组件端常规webpack项目不多说了,以下关键配置
externalsType: "system",
output: {
libraryTarget: "system",
...
},
React组件
export function mount(
container: Element | DocumentFragment,
props?: Record<string, any>,
) {
const client = ReactDOM.createRoot(container);
client.render(
<div>{props?.text}</div>
);
}
Vue组件
// Text.Vue
<template>
<div :style="styles">{{ text }}</div>
</template>
<script lang="ts">
const Text = defineComponent({
props: {
text: String,
}
});
export default Text
</script>
// index.ts
export function mount(container: HTMLElement, props?: Record<string, any>) {
const { createApp } = Vue;
const root = createApp({
setup() {
return () => h(Text, {
...props
});
}
});
root.mount(container);
}
开发好的组件上传到CDN,然后平台通过systemjs加载
import "systemjs";
// 如果webpack中配置了externals, 需要调用addImportMap加载依赖
System.addImportMap({
imports: {
xxx:"http://.../xxx.min.js"
},
});
// 加载组件
System.import("组件加载地址").then(component =>{
const componentContainer = document.createElement("div");
componentContainer.style.width = "100%";
componentContainer.style.height = "100%";
document.body.appendChild(componentContainer);
component.mount(componentContainer, {text:"..."})
})