鹅厂最新开源 WebComponent + iframe 的微前端框架

《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐是一个基于 Web Components + iframe 的微前端框架——wujie。

图片[1]-鹅厂最新开源 WebComponent + iframe 的微前端框架-JieYingAI捷鹰AI

微前端已经是一个非常成熟的领域了,但开发者不管采用哪个现有方案,在适配成本、样式隔离、运行性能、页面白屏、子应用通信、子应用保活、多应用激活、vite 框架支持、应用共享等用户核心诉求都或存在问题、或无法提供支持。

Web Components 是一个浏览器原生支持的组件封装技术,可以有效隔离元素之间的样式,iframe 可以给子应用提供一个原生隔离的运行环境,相比自行构造的沙箱 iframe 提供了独立的 window、document、history、location,可以更好地和外部解耦。无界微前端采用 webcomponent + iframe 的沙箱模式,在实现原生隔离的前提下比较完善地解决了上述问题。

特性

图片[2]-鹅厂最新开源 WebComponent + iframe 的微前端框架-JieYingAI捷鹰AI

无界优势

多应用同时激活在线:框架具备同时激活多应用,并保持这些应用路由同步的能力

组件式的使用方式:无需注册,更无需路由适配,在组件内使用,跟随组件装载、卸载

应用级别的 keep-alive:子应用开启保活模式后,应用发生切换时整个子应用的状态可以保存下来不丢失,结合预执行模式可以获得类似ssr的打开体验

纯净无污染:

性能和体积兼具:

开箱即用:不管是样式的兼容、路由的处理、弹窗的处理、热更新的加载,子应用完成接入即可开箱即用无需额外处理,应用接入成本也极低

快速上手

1 安装

npm install wujie -S

2 主应用

引入:

import { bus, setupApp, preloadApp, startApp, destroyApp } from "wujie";

提示:

如果主应用是vue框架可直接使用 wujie-vue,react框架可直接使用 wujie-react

创建主应用:

setupApp({{ name: "唯一id", url: "子应用地址", exec: true, el: "容器", sync: true }})

预加载:

preloadApp({ name: "唯一id"});

启动子应用:

startApp({ name: "唯一id" });

3 子应用改造

无界对子应用的侵入非常小,在满足跨域条件下子应用可以不用改造。

前提:

子应用的资源和接口的请求都在主域名发起,所以会有跨域问题,子应用必须做 cors 设置

app.use((req, res, next) => {
  // 路径判断等等
  res.set({
    "Access-Control-Allow-Credentials": true,
    "Access-Control-Allow-Origin": req.headers.origin || "*",
    "Access-Control-Allow-Headers": "X-Requested-With,Content-Type",
    "Access-Control-Allow-Methods": "PUT,POST,GET,DELETE,OPTIONS",
    "Content-Type": "application/json; charset=utf-8",
  });
  // 其他操作
});

运行模式:

无界有三种运行模式:单例模式、保活模式、重建模式。

其中保活模式、重建模式子应用无需做任何改造工作,单例模式需要做生命周期改造。

生命周期改造:

改造入口函数:

示例:

if (window.__POWERED_BY_WUJIE__) {
  let instance;
  window.__WUJIE_MOUNT = () => {
    const router = createRouter({ history: createWebHistory(), routes });
    instance = createApp(App);
    instance.use(router);
    instance.mount("#app");
  };
  window.__WUJIE_UNMOUNT = () => {
    instance.unmount();
  };
} else {
  createApp(App).use(createRouter({ history: createWebHistory(), routes })).mount("#app");
}

declare global {
  interface Window {
    // 是否存在无界
    __POWERED_BY_WUJIE__?: boolean;
    // 子应用mount函数
    __WUJIE_MOUNT: () => void;
    // 子应用unmount函数
    __WUJIE_UNMOUNT: () => void;
    // 子应用无界实例
    __WUJIE: { mount: () => void };
  }
}
if (window.__POWERED_BY_WUJIE__) {
  let instance: any;
  window.__WUJIE_MOUNT = () => {
    const router = createRouter({ history: createWebHistory(), routes });
    instance = createApp(App)
    instance.use(router);
    instance.mount("#app");
  };
  window.__WUJIE_UNMOUNT = () => {
    instance.unmount();
  };
  /*
    由于vite是异步加载,而无界可能采用fiber执行机制
    所以mount的调用时机无法确认,框架调用时可能vite
    还没有加载回来,这里采用主动调用防止用没有mount
    无界mount函数内置标记,不用担心重复mount
  */
  window.__WUJIE.mount()
} else {
  createApp(App).use(createRouter({ history: createWebHistory(), routes })).mount("#app");
}

if (window.__POWERED_BY_WUJIE__) {
  window.__WUJIE_MOUNT = () => {
    ReactDOM.render(
      
        
      ,
      document.getElementById("root")
    );
  };
  window.__WUJIE_UNMOUNT = () => {
    ReactDOM.unmountComponentAtNode(document.getElementById("root"));
  };
} else {
  ReactDOM.render(
    
      
    ,
    document.getElementById("root")
  );
}

—END—

开源协议:MIT

开源地址:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
来说点什么吧!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容