微前端架构

qiankun方案

优点

1.与技术栈无关,子应用独立开发、独立部署

使用

本文档以vue项目为示例,主应用采用history路由模式,子应用一个为hash模式,一个为history模式
qainkun规定:如果主应用是history模式,则子应用可以是hashhistory模式;如果主应用是hash模式,则子应用必须为hash模式。详情见官方文档(微应用的路由模式如何选择

主应用配置

1.安装qiankun

npm i qiankun -S

2.在主应用入口文件中注册微应用

import { registerMicroApps, start } from 'qiankun';

// 注册子应用列表
registerMicroApps([
  {
    name: 'vue2App1', // 子应用名称
    entry: process.env.VUE_APP_APP1, // 子应用入口地址,默认会加载该地址下的html文件,可利用环境变量区分不同环境的入口地址
    container: '#subapp-container', // 加载的容器
    activeRule: '/vue2App1' // 匹配的路由规则,访问以‘/vue2App1’开头的URL时会走这里
  },
  {
    name: 'vue2App2',
    entry: process.env.VUE_APP_APP2,
    container: '#subapp-container',
    activeRule: '/vue2App2',
  },
]);

// 启动微服务
start();

3. 在路由文件中增加指向子应用的路由

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
const routes = [
  {
    path: '/',
    redirect: '/main'
  },
  {
    path: '*',
    name: '404',
    component: () => import('@/views/404')
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login')
  },
  {
    path: '/main',
    name: 'Main',
    component: () => import('@/views/Main'),
    redirect: '/main/home',
    children: [
      {
        path: 'home',
        name: 'Home',
        component: () => import('@/views/Home')
      }
    ]
  },
  {
  	// 以‘/vue2App1/‘开头的url会匹配到该路由
  	// 子应用列表中的activeRule属性匹配这里的路由
    path: '/vue2App1/*',
    component: () => import('@/views/Main')
  },
  {
	// 以‘/vue2App2/‘开头的url会匹配到该路由
	// 子应用列表中的activeRule属性匹配这里的路由
    path: '/vue2App2/*',
    component: () => import('@/views/Main')
  }
]

const router = new VueRouter({
  mode: 'history',
  routes,
})
export default router

4.指定子应用加载容器

<template>
  <div class="main">
    <header>
      <div class="header-content">
        <span>这是主应用的main页面</span>
      </div>
      <div style="margin-top: 16px; line-height:22px">
      	<!-- 指向子应用中‘/’匹配到的路由 -->
      	<router-link to="/vue2App1/">vue2App1</router-link>
      	<!-- 指向子应用中‘/app1/login’匹配到的路由 -->
        <router-link to="/vue2App1/app1/login">vue2App1</router-link>
        
        <!-- 指向hash模式的子应用中‘/main/demo1’匹配到的路由 -->
        <router-link to="/vue2App2/#/main/demo1">vue2App2</router-link>
      </div>
    </header>
    <div class="main-content">
      <!-- 主应用渲染容器 -->
      <router-view/>
      <!-- 子应用渲染容器 -->
      <!-- 与子应用注册列表中的container属性一致 -->
      <div id="subapp-container"></div>
    </div>
  </div>
</template>
微应用配置

vue2项目
1.在 src 目录新增 public-path.js

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

2.入口文件 main.js 修改,引入public-path.js,区分应用挂载的容器(独立运行还是乾坤环境运行)

// 需要引入public-path.js
import './public-path';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';

Vue.config.productionTip = false;

let router = null;
let instance = null;
function render(props = {}) {
  const { container } = props;
  router = new VueRouter({
  	// base默认为/, 在乾坤环境手动设置为主应用中activeRule值
  	// 如果子应用为hash模式则无需配置base
    base: window.__POWERED_BY_QIANKUN__ ? '/vue2App1' : '/',
    mode: 'history',
    routes,
  });

  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时,__POWERED_BY_QIANKUN__变量存在则为qiankun环境运行
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// 子应用初始化时调用一次
export async function bootstrap() {
  console.log('[bootstrap');
}
// 每次进入应用都会调用
export async function mount(props) {
  console.log('mount', props);
  render(props);
}
// 每次卸载应用都会调用
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}

3.打包配置修改(vue.config.js

const { name } = require('./package');
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*', // 允许跨域
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`, // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    },
  },
};

iframe方案

<!-- html框架标签 在页面中画一个区域来展示src里的页面 -->
<iframe src="https://qiankun.umijs.org/zh" width="800px" height="500px"></iframe>
// 获取iframe内的document和window 
let iframe = document.querySeletor("iframe")
iframeDoc = iframe.contentWidow.document
iframeWin = iframe.contentWindow

优点

1.使用简单,每个iframe内的内容完全隔离、互不影响,适合嵌套简单页面

缺点

1.url不同步。刷新浏览器,iframe中的路由会丢失
2.ui 不同步,DOM 结构不共享
3.全局上下文完全隔离,内存变量不共享
4.慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值