前端微应用qiankun+vue3.0+vue2.0

微前端

微前端特点

  1. 技术栈无关 主框架不限制接入应用的技术栈,子应用可自主选择技术栈
  2. 独立开发/部署 各个团队之间仓库独立,单独部署,互不依赖
  3. 增量升级 当一个应用庞大之后,技术升级或重构相当麻烦,而微应用具备渐进式升级的特性
  4. 独立运行时 微应用之间运行时互不依赖,有独立的状态管理
  5. 提升效率 应用越庞大,越难以维护,协作效率越低下。微应用可以很好拆分,提升效率

微前端方案

  1. 基于 iframe 完全隔离的方案
  2. 基于 single-spa 路由劫持方案
  3. 阿里 qiankun
iframe
优点
  • 非常简单,无需任何改造
  • 完美隔离,JS、CSS 都是独立的运行环境
  • 不限制使用,页面上可以放多个 iframe 来组合业务
缺点
  • 无法保持路由状态,刷新后路由状态就丢失
  • 完全的隔离导致与子应用的交互变得极其困难,只能采用postMessage方式
  • iframe 中的弹窗无法突破其本身
  • 整个应用全量资源加载,加载太慢
single-spa
qiankun
特点
  • 基于 single-spa 封装,提供了更加开箱即用的 API。
  • 技术栈无关,任意技术栈的应用均可 使用/接入,不论是React/Vue/Angular/JQuery 还是其他等框架。
  • HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
  • 样式隔离,确保微应用之间样式互相不干扰。
  • JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
  • 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
  • umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
快速使用
主应用配置
$ yarn add qiankun # 或者 npm i qiankun -S

main.js 主应用中注册子应用

import {
    registerMicroApps,
    start,
    setDefaultMountApp
} from 'qiankun'


// 在主应用中注册子应用
registerMicroApps([{
    name: "vue app",
    entry: "//localhost:8090", // 子应用链接
    container: '#vue',         // 子应用容器
    activeRule: '/vue',        // 跳转子应用路由
    props: {
        appContent: '我是子应用传给主应用的值'
    }
}
])
setDefaultMountApp("/vue")
// 启动
start()

router/index.js 主项目是 vue3 + vue-router@4配置

//主应用使用的嵌套路由
router.beforeEach((to, from, next) => {
  if (!window.history.state.current) window.history.state.current = to.fullPath;
  if (!window.history.state.back) window.history.state.back = from.fullPath;
  // 手动修改history的state
  return next();
});

子应用容器

  <div id="vue"></div>

webpack配置 vue.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server:{
    port:9000,
    headers: {			// 允许子应用跨域
      'Access-Control-Allow-Origin': '*',
    }
  }
})
vue2.0 子应用配置

src/public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

main.js

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import './public-path'
 
Vue.config.productionTip = false;
 
let instance = null;
function render(props = {}) {
  const { container } = props;
  instance = new Vue({
    router,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector("#app-vue") : "#app-vue");
}
 
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}
 // 导出相应的生命周期钩子
 
/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */

export async function bootstrap() {
  console.log("bootstraped");
}
/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  console.log("mount");
  render(props);
}
/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount() {
  console.log("unmount")
  instance.$destroy();
  instance.$el.innerHTML = "";
  instance = null;
}

路由配置 router/index.js

const router = new VueRouter({
  // 这里和主应用中注册子应用时的activeRule对应
  base: window.__POWERED_BY_QIANKUN__ ? "/vue" : "/", //  base路由和注册子应用入口保持一致
  mode: "history",
  routes,
});

webpack配置 vue.config.js

const { defineConfig } = require('@vue/cli-service')
const { name } = require("./package");
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    port: 8090, //子应用启动端口号,不可随意修改,与上文中父应用注册的子应用端口号对应
    headers: {
      "Access-Control-Allow-Origin": "*", //循序跨域
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: "umd", // 把微应用打包成 umd 库格式
      // jsonpFunction: `webpackJsonp_${name}`,
    },
  },
})

项目中index.html 和App.vue中的id 都改为 app-vue

vue3.0子应用配置

main.js

import { createApp } from 'vue'
import App from './App.vue'
import { createWebHistory } from 'vue-router'
import createRouter from "./route"
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'

let router = null
let instance = null
let history = null

function render(props) {
  console.log("__POWERED_BY_QIANKUN__", qiankunWindow.__POWERED_BY_QIANKUN__)
  const container = props ? props.container : undefined
  history = createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/two' : '/')
  router = createRouter(history)
  instance = createApp(App)
  instance.use(router)
  instance.mount(container ? container.querySelector('#app-vue3') : '#app-vue3')
}
renderWithQiankun({
  mount(props) {
    render(props)
    instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange
    instance.config.globalProperties.$setGlobalState = props.setGlobalState
  },
  bootstrap() {
    console.log('%c%s', 'color: green;', 'vue3.0 app bootstraped')
  },
  unmount() {
    instance.unmount()
    instance._container.innerHTML = ''
    instance = null
    router = null
    history.destroy()
  },
  update() {
    console.log('update')
  }
})

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  render(undefined)
}

route.js

import { createRouter } from 'vue-router'
const routes = [
  {
    path:'/',
    name:'Home',
    component:()=>import('../view/Home.vue')
  }
]
export default function (history) {
  return createRouter({
    history: history,
    routes,
  })
}

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from "vite-plugin-qiankun"


// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      vue(),
      qiankun("VUE3.0", {
        useDevMode: true
      })
  ],
  server:{
    port:5000
  }
})
npm install vite-plugin-qiankun

源码
主应用: https://gitee.com/wy-yyb/vue3-main.git
vue2子应用:https://gitee.com/wy-yyb/vue2.0.git
vue3子应用https://gitee.com/wy-yyb/vue3.0.git

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值