无界微前端项目搭建与部署

1,016 阅读2分钟

前言

很久没更新了,说忙也在忙,说不忙也在划! 最近公司需要搭建一个新的项目框架,把之前的系统做整合,让我使用ifram搞,果断拒绝,给他安利无界微应用。虽然之前只是在自己项目中跑,没在实际中用过。那既然没用过,那肯定得用,开搞!

主应用搭建

使用 vite 脚手架进行 vue3 项目搭建。在之前的文章中有相关的介绍,就不再赘述juejin.cn/post/720499… 走完上面的流程默认vu3项目已经可以运行

主应用改造

安装wujie

"wujie-vue3": "^1.0.18"

main.ts 中 引入 WujieVue 并使用 setupApp 进行子应用设置

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

import WujieVue from 'wujie-vue3'
const { setupApp } = WujieVue
import { micros, getUrl } from '@/utils'
import lifecycles from './lifecycles' // 生命周期函数

const app = createApp(App)
const render = () => {
  app.use(createPinia())
  app.use(router)
  app.use(WujieVue)
  app.mount('#app')
}
render()
// 模拟接口查询,实现动态子应用加载与动态路由添加
const setMiro = () =>
  new Promise((resolve) => {
    for (const value of micros) {
      const obj: any = {
        path: `/${value.name}`,
        name: value.name,
        component: () => import(`@/views/micro/index.vue`) //子应用使用同一个wujie配置
      }
      router.addRoute('home', obj)
      setupApp({
        name: value.name, 
        url: getUrl(value.name, micros),
        exec: true,
        ...lifecycles
      })
    }
    resolve(true)
  })
// eslint-disable-next-line require-await
router.beforeEach(async (to, _from, next) => {
  if (router.getRoutes().length <= 3) {
    // 如果路由个数为基础路由,则说明没有进行路由和子应用添加,需要动态添加,添加完成,根据路由地址进行跳转
    await setMiro()
    next({
      path: to.path,
      query: { ...to.query }
    })
  } else {
    next()
  }
})

lifecycles.ts 引入,暂时函数里面还用不到,先放着

const lifecycles = {
  beforeLoad(appWindow: any) {
    // 第一次子应用的时候执行
    // 打开加载动画
  },
  beforeMount() {
    // console.log('beforeMount()-----------------');
  },
  afterMount(appWindow: any) {
    // 自应用第一次挂载到页面上之后执行(后续会缓存,不会执行)
    // 关闭加载动画
  },
  beforeUnmount(appWindow: any) {
    // console.log('beforeUnmount()-----------------');
  },
  afterUnmount(appWindow: any) {
    // console.log('afterUnmount()-----------------');
  },
  activated(appWindow: any) {
    // console.log(appWindow)
  },
  deactivated(appWindow: any) {
    // console.log('deactivated()-------------------------');
  }
}

export default lifecycles

micros 为我们定义的子应用,也是顶部的tab,切换tab,跳转相应的子应用;getUrl 根据传值过来的name,进行子应用路径返回。如,我们切换到数据规则tab 时,url 返回//localhost:8001/data-rule/。当发布线上时,因为部署在统一域名端口下,所有直接取对应的路径 /data-rule/

export const micros = [
  {
    name: 'data-rule',
    desc: '数据规则',
    port: 8001
  },
  {
    name: 'event-rule',
    desc: '事件规则',
    port: 8002
  }
]
export const getUrl = (appName: string, mciroList = micros) => {
  const config = mciroList.find((item) => item.name === appName)
  if (import.meta.env.MODE === 'development') {
    return `//localhost:${config.port}/${config.name}/`
  }
  return `/${config.name}/`
}

动态加载路由的页面需要引入 wujie alive 为true 保活状态 sync 页面刷新依旧保持在当前页面

<template>
  <div class="sub-app">
    <WujieVue width="100%" height="100%" :name="name" :url="url" :alive="true" sync />
  </div>
</template>
<script lang="ts" setup>
import { getUrl } from '@/utils'
const router: any = useRouter()
const url = computed(() => getUrl(router.currentRoute.value.name))
const name = computed(() => router.currentRoute.value.name)
</script>
<style scoped lang="scss">
.sub-app {
  height: 100%;
  width: 100%;
  .wujie_iframe {
    height: 100%;
  }
}
</style>

子应用改造

子应用改造比较简单

在 main.ts 中加入无界判断

import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)
const render = () => {
  app.use(createPinia())
  app.use(router)
  // console.log(app._context.components)
  app.mount('#app')
}

declare global {
  interface Window {
    // 是否存在无界
    __POWERED_BY_WUJIE__?: boolean
    // 子应用mount函数
    __WUJIE_MOUNT: () => void
    // 子应用unmount函数
    __WUJIE_UNMOUNT: () => void
    // 子应用无界实例
    __WUJIE: { mount: () => void }
    $wujie: any
  }
}
if (window.__POWERED_BY_WUJIE__) {
  // console.log(window.$wujie)
  window.__WUJIE_MOUNT = () => {
    render()
  }
  window.__WUJIE_UNMOUNT = () => {
    app.unmount()
  }
  window.__WUJIE.mount()
} else {
  render()
}

在路由配置中添加路径

例如data-rule 子应用

image.png

vite.config.ts 修改打包路径与本地运行端口

base 为我们打包后项目运行根路径

port 为本地运行端口

outDir 根据个人需要,看是否需要修改输出位置。(输出放一块的话,在nginx发布方便)

image.png 放一下demo效果,切换tab 更换子应用

image.png

image.png

总结一下

实现一个微应用,主要需要对主应用进行改造,引入无界,配置子应用端口,与路由路径,实现子应用跳转。子应用如果在满足跨域的情况下可以不用改造。附上代码仓库 gitee.com/Provens/mic…

无界学习地址 wujie-micro.github.io/doc/guide/s…

下一步计划

将打包项目部署在服务器,进行真实场景添加,子应用跳转,主应用子应用数据传参等,引入外部子应用(不同域下,ng转发等)。