微前端-qiankun

101 阅读4分钟

1.微前端作用

微前端一般用于整合多个项目。例如有一个vue项目和react项目,一般来说想整合起来就得使用iframe,而iframe确实能够胜任,但是其隔离性太强导致两项目无法很好通信,而微前端能很好的解决这一点。(不过iframe也可以使用postMessage来通信,就是时机不好把握,onload和mounted都不能保证iframe渲染完成,不晓得啥原因) 另外一个优势就是渲染机制问题,iframe离开页面需要重新渲染,而这个不会,本质上是启动了多个服务,又没关,数据一直存在那,理论上应该很耗资源才对。(待验证)

2.为什么要学微前端

简历上没啥写的,看上去这个比较叼,扯上微服务了

  • 以下是ai写的,说的挺对的
  1. 模块化与独立性:微服务架构通过将复杂的系统分解为独立的模块,使开发团队能够专注于单个服务的开发和维护,减少了代码耦合。
  2. 技术多样性:每个服务可以使用最适合其需求的技术栈和编程语言,而不受其他模块的限制。
  3. 高扩展性:微服务架构允许根据需求扩展特定服务,而不必扩展整个应用,提高资源利用率。
  4. 提高系统可靠性:在微服务架构中,某个服务的故障通常不会影响到其他服务的正常运行,增强了系统的容错能力。
  5. 快速迭代与交付:微服务的独立部署特性使得团队可以在不影响整体系统的情况下快速更新和迭代单个模块。
  6. 敏捷开发与快速迭代:微服务架构赋予了开发团队敏捷性,每个微服务作为独立的开发单元,团队能够依据业务需求灵活调整优先级,并行推进开发进程。
  7. 强大的可扩展性:微服务架构允许企业根据业务需求,对特定的微服务进行精准扩容或缩容。
  8. 卓越的容错能力:微服务架构拥有强大的故障隔离机制,当某个微服务突发故障,故障被牢牢锁定在该服务内部,不会在整个系统中蔓延。
  9. 技术选型多元化:微服务架构允许每个微服务依据自身业务特性与性能要求,自由选择最合适的技术栈。
  10. 高效的团队协作:在微服务架构的舞台上,小型跨职能团队成为主角,每个团队聚焦负责一个或几个微服务的全生命周期管理。

3.微前端使用

这里有个例子juejin.cn/post/687546… clone里面的example。

image.png

直接看结构,main就是最外层,sub-*就是子组件。

两个注意点

怎么确认有哪些子组件 main/src/micro-app.js里写了

import store from './store'

const microApps = [
  {
    name: 'sub-vue',
    entry: process.env.VUE_APP_SUB_VUE,
    activeRule: '/sub-vue'
  },
  {
    name: 'sub-react',
    entry: process.env.VUE_APP_SUB_REACT,
    activeRule: '/sub-react'
  },
  {
    name: 'sub-html',
    entry: process.env.VUE_APP_SUB_HTML,
    activeRule: '/sub-html'
  }
]

const apps = microApps.map(item => {
  return {
    ...item,
    container: '#subapp-viewport', // 子应用挂载的div
    props: {
      routerBase: item.activeRule, // 下发基础路由
      getGlobalState: store.getGlobalState // 下发getGlobalState方法
    }
  }
})

export default apps

第二点,怎么通信?main/src/store.js

import { initGlobalState } from 'qiankun'
import Vue from 'vue'

// 父应用的初始state
// Vue.observable是为了让initialState变成可响应:https://cn.vuejs.org/v2/api/#Vue-observable。
const initialState = Vue.observable({
  user: {
    name: 'zhangsan'
  }
})

const actions = initGlobalState(initialState)

actions.onGlobalStateChange((newState, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log('main change', JSON.stringify(newState), JSON.stringify(prev))

  for (const key in newState) {
    initialState[key] = newState[key]
  }
})

// 定义一个获取state的方法下发到子应用
actions.getGlobalState = (key) => {
  // 有key,表示取globalState下的某个子级对象
  // 无key,表示取全部

  return key ? initialState[key] : initialState
}

export default actions

来到sub-vue,直接使用完事,通信解决。其他的扩展暂且不知道


<script>
import { mapState, mapActions } from 'vuex'
export default {
  computed: {
    // 通过global获取user的信息
    ...mapState('global', {
      user: state => state.user
    }),
    isInQiankun () {
      return window.__POWERED_BY_QIANKUN__
    }
  },
  methods: {
    // setGlobalState 是在 /common/src/store/global-register.js中定义的
    ...mapActions('global', ['setGlobalState']),
    gotoSubReact () {
      history.pushState(null, 'sub-react', '/sub-react')
    },
    changeUsername () {
      // 也可通过 store.commit('global/setGlobalState', { user: '李四' }) 进行操作
      this.setGlobalState({
        user: { name: '李四' + Math.round(Math.random() * 100) }
      })
    },
    openSubVue () {
      if (!this.isInQiankun) {
        alert('当前已经是单独运行的子应用')
        return
      }

      // window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__ 是qiankun注入的子应用对应的地址,谨慎使用,生产环境建议将跳转地址维护在环境变量中
      window.open(window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__)
    }
  }
}
</script>

写的文章真烂哈。。