当前位置: 首页 > news >正文

微前端 Micro app

qiankun官网

wujie官网

Micro app 官网

Micro app + vite 子应用DEMO

通过调研:乾坤、wujie 、microapp 官网、github、搜索相关资料,发现目前micro app 对现在的vite支持的最好。

验证Micro app当子应用是vite的时候是否会对沙箱有影响;

下载Micro app + vite 子应用DEMO 子应用DEMO本地启动服务;

node:v18.17.0
micro app:^1.0.0-rc.4
vite:5.0.11

在父应用添加:

window.testChildValue  = {
    txt: 'testTxt'
};
console.log('父应用输出:',window.testChildValue.txt ); // 父应用输出:testTxt

在子应用添加:

setTimeout(() => {
	console.log('子应用输出:', window.testChildValue ); // 子应用输出:undefined
})

注意事项

  1. 父子应用:locstorage、cookie、sessionStorage 存储命名添加项目头部,防止命名冲突。
  2. 如全局样式、!important 规则会绕过css沙箱机制,导致父应用使用!important的全局样式影响到子应用,父应用尽量避免全局样式使用 !important。
  3. 父应用与子应用的根节点的ID名称(index.html根节点的ID名称)不能重复
  4. 子应用router必须使用history模式
  5. 子应用elment-plus的样式不能在main.ts直接引用,因为element会声明很多全局对象,影像父应用的样式

使用 vite-plugin-style-import@2.0.0 版本 按需加elment-plus的样式,vite.config.ts:

import { createStyleImportPlugin, ElementPlusResolve } from "vite-plugin-style-import"

export default defineConfig((mode): any => {
  const env = loadEnv(mode.mode, process.cwd())
  return {
    plugins: [
	......
      createStyleImportPlugin({
        resolves: [ElementPlusResolve()],
        libs: [
          {
            libraryName: "element-plus",
            esModule: true,
            resolveStyle: (name) => {
              // 屏蔽element-plus不需要按需加载样式的选项
              if (name === "click-outside" || name === "dayjs") {
                return ""
              }
              return `element-plus/es/components/${name.replace(/^el-/, "")}/style/css`
            }
          }
        ]
      }),
      
   ......
  }
})

子应用接入micro-app

main.ts

import { createApp, toRaw } from "vue"
import App from "@/App.vue"
import { setupStore } from "@/store"
import { constantRouterMap } from "@/router"
import { createRouter, createWebHistory } from "vue-router"
import type { RouteRecordRaw } from "vue-router"
import { filterAsyncRoutes } from "@/utils/permission"
import "@/styles/index.scss"
import "virtual:svg-icons-register"



/**
   * 解决火狐(版本大于107)兼容性问题
   * 代理 instanceof Element 方法, 手动监测 element 是否是 dom 元素
   * */
if (
  navigator.userAgent.indexOf('Firefox') > -1 &&
  +navigator.userAgent.match(/Firefox\/([\d.]+)/)![1] > 107
) {
  Object.defineProperty(Element, Symbol.hasInstance, {
      value: function (node: any) {
          if (typeof node !== 'object' || !node) return false;
          node = node.__proto__;
          while (node) {
              // 重写 instanceof 判断逻辑
              if (
                  Object.prototype.toString.call(node) ===
                  this.prototype.toString()
              )
                  return true;
              node = node.__proto__;
          }
          return false;
      },
  });
}


declare global {
  interface Window {
      microApp: any
      mount: CallableFunction
      unmount: CallableFunction
      __MICRO_APP_ENVIRONMENT__: string
      __MICRO_APP_BASE_ROUTE__: string
      __MICRO_APP_NAME__: string
      __MICRO_APP_PUBLIC_PATH__: string
      __MICRO_APP_BASE_APPLICATION__: string
  }
}
function handleMicroData() {
  // 监听基座下发的数据变化
  // window.microApp?.addDataListener((data: any) => {
      // console.log('child-vite addDataListener:', data)
  // }, true)

  // 向基座发送数据
  setTimeout(() => {
      window.microApp?.dispatch({ myname: '应用名称' })
  }, 3000)
}

let app: any = null
let router: any = null
let history: any = null

// 将渲染操作放入 mount 函数
window.mount = () => {
  if(window.__MICRO_APP_ENVIRONMENT__){
    const data = window.microApp.getData() 
    if(constantRouterMap[0].path === "/" && data.routes){
     // filterAsyncRoutes:根据如有表寻找 src/views/ 文件,并绑定到路由表上的component属性上
      constantRouterMap[0].children = [ ...filterAsyncRoutes(toRaw(data.routes)) ]
    }
  }
  history = createWebHistory(window.__MICRO_APP_BASE_ROUTE__ || import.meta.env.BASE_URL)
  router = createRouter({
    history: history,
    strict: true,
    routes: constantRouterMap as RouteRecordRaw[],
    scrollBehavior: () => ({ left: 0, top: 0 })
  })


  app = createApp(App)
  setupStore(app)
  app.use(router)
  app.mount("#xxxApp")
  handleMicroData()
}

// 将卸载操作放入 unmount 函数
window.unmount = () => {
  app && app.unmount()
  history && history.destroy()
  app = null
  router = null
  history = null
  console.log('微应用vite卸载了 -- UMD模式');
}

// 非微前端环境直接渲染
if (!window.__MICRO_APP_ENVIRONMENT__) {
  window.mount()
}

vite.config.ts 本地设置跨域支持。

...
// https://vitejs.dev/config/
export default defineConfig({
  base: "/xxx/", //项目基础路径 micro app name
  ...
  server: {
    port: xxxx,
    host: true,
    headers: {
      'Access-Control-Allow-Origin': '*'
    },
    ...
  }
})

相关文章:

  • 数学建模之数学模型—2:非线性规划
  • MySQL 连表查询:原理、语法与优化
  • 005:Cesium.viewer 知识详解、示例代码
  • 小迪安全-24天-文件管理,显示上传,黑白名单,访问控制
  • 【R语言】dplyr包经典函数summarise函数
  • 永洪科技旗下BI产品,成功入选“金融信创优秀解决方案“
  • 模版语法vscode
  • 云计算及其他计算
  • 【LeetCode刷题之路】leetcode155.最小栈
  • Windows 11【1001问】如何下载Windows 11系统镜像
  • 【2025信息安全软考重点考点归纳】实时更新
  • 首发!三维街景数据产品V0.1版发布
  • 网络安全入门|从防护到溯源:HTTP慢速攻击的深度对抗
  • 力扣hot100——二叉树的右视图
  • 基于同轴聚类点云去重的铆钉高度测量
  • [数学] 常用数学公式(逐步更新完善)
  • html中rel、href、src、url的区别
  • Python项目源码33:待办事项列表应用2.0(命令行界面+Json+类)
  • DeepSeek 提示词:高效的提示词设计
  • GIST框架:深度学习助力组织病理学与转录组学的空间整合分析|顶刊精析·25-02-24
  • 雷军:小米芯片采用3纳米制程,首款SUV“YU7”即将发布
  • 石家庄桥西区通报“中药液”添加安眠药问题:对医院立案调查
  • 61岁云浮市律师协会副会长谭炳光因突发疾病逝世
  • 新闻1+1丨强对流天气频繁组团来袭,该如何更好应对?
  • 试点首发进口消费品检验便利化措施,上海海关与上海商务委发文
  • 侵害孩子者,必严惩不贷!3名性侵害未成年人罪犯被执行死刑