利用Systemjs使React和Vue组件共存

488 阅读1分钟

需求

最近在做一个代码平台,其中一个核心需求是可以使用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:"..."})
})

按照上面的原理,最终实现antd和element的组件可以在一个系统上共存

1692639938712.jpg

参考

github.com/drinkjs/moj…

github.com/drinkjs/moj…