Vue + qiankun 搭建微前端

Vue + qiankun 搭建微前端

本章节基于 Vue + qianakun 的方式搭建的微前端,微前端有主应用与微应用构成。

**主应用:**Vue3 + Vite

微应用:

  1. Vue2 + Webpack5
  2. Vue3 + Vite

主应用配置:

  1. 主应用需安装 qiankun 微前端架构 (本章节使用的是最新版本:2.10.16)

    pnpm add qiankun 或者 # yarn add qiankun # 或者 npm i qiankun -S
    
  2. 注册微应用:在 src 目录新增 qiankun/index.ts

import {registerMicroApps, start, addGlobalUncaughtErrorHandler} from ‘qiankun’
import type {RegistrableApp, FrameworkLifeCycles} from ‘qiankun/lib’

// 微应用注册信息
const apps: RegistrableApp<object>[] = [
  // 
  {
    name: 'sonVue2', // 微应用名称
    entry: '//localhost:3002/child/son-vue2', // 微应用入口
    container: '#container', // 微应用挂载节点
    activeRule: '/son-vue2', // 微应用路由
  },
  {
    name: 'sonVue3', // 微应用名称
    entry: '//localhost:3003/', // 微应用入口
    container: '#container', // 微应用挂载节点
    activeRule: '/son-vue3', // 微应用路由
  }

]

// 全局的微应用生命周期钩子
const lifecycle: FrameworkLifeCycles<Object> = {
  beforeLoad: async (app) => {
    console.log(app)
  },
  beforeMount: async (app) => {
    console.log(app)
  },
  afterMount: async (app) => {
    console.log(app)
  },
  beforeUnmount: async (app) => {
    console.log(app)
  },
  afterUnmount: async (app) => {
    console.log(app)
  }
}

registerMicroApps(apps, lifecycle)

// 添加全局的未捕获异常处理器
addGlobalUncaughtErrorHandler((event: any) => {
  const {message: msg} = event
  if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
    console.error('微应用加载失败')
  } else {
    console.error(event)
  }
})
export default start

```
  1. 封装 qiankun 全局通信方法(可选):在 src 目录新增 qiankun/actions.ts

    import {initGlobalState} from 'qiankun'
    import type {MicroAppStateActions, OnGlobalStateChangeCallback} from 'qiankun/lib'
    
    class Actions {
      declare actions: MicroAppStateActions
    
      // 设置全局状态
      setAction(state: Record<string, any>): void {
        this.actions = initGlobalState(state)
      }
    
      // 监听全局状态
      onGlobalStateChange(callback: OnGlobalStateChangeCallback, fireImmediately?: boolean): void {
        return this.actions.onGlobalStateChange(callback, fireImmediately)
      }
      
      // 修改全局状态
      setGlobalState(state: Record<string, any>): boolean {
        return this.actions.setGlobalState(state)
      }
      
      // 移除当前应用的状态监听
      offGlobalStateChange(): boolean {
        return this.actions.offGlobalStateChange()
      }
    }
    
    export default new Actions()
    
    
  2. vue 路由配置

    // router/index
    import {createRouter, createWebHistory} from 'vue-router'
    
    const router = createRouter({
      routes: [...],
      // 路由模式配置为history模式
      history: createWebHistory(import.meta.env.BASE_URL)
    })
    // 处理微应用内部路由跳转后无法切换到主应用或其他微应用问题
    router.afterEach((to, from) => {
      const current = router.options.history.state.current
      Object.assign(router.options.history.state, {
        current: current === '/' ? '/' : to.fullPath
      })
    })
    
    export default router
    
    
  3. main.ts 中应用

    import '@/assets/main.scss'
    import {createApp} from 'vue'
    import App from './App.vue'
    import router from './router'
    import {createPinia} from "pinia";
    import {useMessageStore} from "@/stores/message";
    import start from '@/qiankun/index' // 引用注册微应用文件
    import actions from '@/qiankun/actions'; // 引用qiankun通信
    
    const app = createApp(App)
    app.use(router)
    app.use(createPinia())
    app.mount('#host-app')
    
    const store = useMessageStore()
    
    // 设置全局状态
    actions.setAction({message: store.message})
    // 监听全局状态
    actions.onGlobalStateChange((state, prev) => {
      store.setMessage(state.message)
    })
    
    // 启动qiankun
    start({
      prefetch: true, // 开启预加载
      sandbox: true // 开启沙箱
    })
    
    
  4. 修改 App.vue

    <script setup lang="ts">
        ...
    </script>
    
    <template>
    	...
    	<!-- 微应用挂载节点 -->
        <div id="container"></div>
    </template>
    
    <style scoped lang="scss">
        ...
    </style>
    
    

微应用搭建:

Vue2 + Webpack5

微应用无需安装额外的依赖。

  1. src 目录新增 public-path.js

    if (window.__POWERED_BY_QIANKUN__) {
        __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
    
  2. 修改 vue.config.js 配置

    const {defineConfig} = require('@vue/cli-service')
       
       module.exports = defineConfig({
           devServer: {
               port: 3002,
               host: '0.0.0.0',
                // 允许本地跨域请求
               headers: {
                   'Access-Control-Allow-Origin': '*',
               },
           },
           // 配置公共访问路径
           publicPath: '/child/son-vue2/',
           configureWebpack: {
               output: {
                   library: `sonVue2`, // 微应用名称
                   libraryTarget: 'umd', // 打包成 umd 库格式
                   chunkLoadingGlobal: `webpackJsonp_sonVue2`,
               },
           },
           transpileDependencies: true,
       })
    
  3. 封装 qiankun 全局通信方法(可选):在 src 目录新增 qiankun/actions.js

    class Actions {
        actions = {
            onGlobalStateChange: null,
            setGlobalState: null,
            offGlobalStateChangeL: null
        }
        
    	// 初始化 qiankun 全局通信
        initAction(actions) {
            this.actions = actions
        }
        
    	// 监听全局状态
        onGlobalStateChange() {
            return this.actions.onGlobalStateChange(...arguments)
        }
    
    	// 修改全局状态
        setGlobalState() {
            return this.actions.setGlobalState(...arguments)
        }
    }
    
    export default new Actions();
    
    
  4. vue 路由配置

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
     	routes:[...],
        base: window.__POWERED_BY_QIANKUN__ ? '/' : '/child/son-vue2', // 配置微应用访问路径
        mode: 'history', // 路由模式配置为history模式
    })
    
    export default router
    
    
  5. main.js 中应用

    import './public-path';
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import actions from "@/qiankun/actions"; // 引用qiankun通信
    
    Vue.config.productionTip = false
    let app = null;
    
    function render(props = {}) {
        const {container} = props;
        app = new Vue({
            router,
            render: (h) => h(App),
        }).$mount(container ? container.querySelector('#app') : '#app');
    }
    
    // 独立运行时
    if (!window.__POWERED_BY_QIANKUN__) {
        render();
    }
    
    // 导出微应用生命周期钩子
    // 初始化
    export async function bootstrap() {
    	console.log('bootstrap')
    }
    
    // 挂载
    export async function mount(props) {
        actions.initAction(props) // 初始化qiankun通信
        render(props);
    }
    
    // 卸载
    export async function unmount() {
        app.$destroy();
        app.$el.innerHTML = '';
        app = null;
    }
    
    

Vue3 + Vite

由于是 Vite 应用需要安装 Vite 版本的 qiankun 依赖

pnpm add vite-plugin-qiankun -D 或者 # yarn add vite-plugin-qiankun -D # 或者 npm i vite-plugin-qiankun -D
  1. 修改 vite.config.js 配置

    import {fileURLToPath, URL} from 'node:url'
    
    import {defineConfig} from 'vite'
    import vue from '@vitejs/plugin-vue'
    import qiankun from 'vite-plugin-qiankun'
    
    export default defineConfig({
        plugins: [
            vue(),
         	// 配置qiankun    
            qiankun('sonVue3', {
                useDevMode: true
            })
        ],
    
        base: '/child/son-vue3/',
        server: {
            port: 3003,
            host: '0.0.0.0',
            cors: true, // 允许本地跨域请求
        },
        
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url))
            }
        }
    })
    
    
  2. 封装 qiankun 全局通信方法(可选):在 src 目录新增 qiankun/actions.js

    class Actions {
        actions = {
            onGlobalStateChange: null,
            setGlobalState: null,
            offGlobalStateChangeL: null
        }
    
    	// 初始化 qiankun 全局通信
        initAction(actions) {
            this.actions = actions
        }
    
    	// 监听全局状态
        onGlobalStateChange() {
            return this.actions.onGlobalStateChange(...arguments)
        }
    
    	// 修改全局状态
        setGlobalState() {
            return this.actions.setGlobalState(...arguments)
        }
    }
    
    export default new Actions();
    
    
  3. vue 路由配置

    import {createRouter, createWebHistory} from 'vue-router'
    import {qiankunWindow} from 'vite-plugin-qiankun/dist/helper.js'
    const router = createRouter({
        routes: [...],
        // 路由模式配置为history模式,并配置微应用访问路径
        history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/' : '/child/son-vue3/'),
    })
    
    export default router
    
    
  4. main.js 中应用

    import './assets/main.css'
    
    import {createApp} from 'vue'
    import App from './App.vue'
    import router from './router'
    import {renderWithQiankun, qiankunWindow} from 'vite-plugin-qiankun/dist/helper'
    import actions from "@/qiankun/actions.js"; // 引用qiankun通信
    
    let app = null
    
    function render(props = {}) {
        const {container} = props;
        app = createApp(App)
        app.use(router)
        app.mount(container ? container.querySelector('#son-vue3') : '#son-vue3');
    }
    
    // 如果不是在 qiankun 环境中运行,则独立启动
    if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
        render()
    }
    
    // 初始化
    function bootstrap() {
        console.log('bootstrap')
    }
    
    // 挂载
    function mount(props) {
        actions.initAction(props) // 导出微应用生命周期钩子
        render(props)
    }
    
    // 卸载
    function unmount(props) {
        app.unmount();
    }
    
    // 导出微应用生命周期钩子
    renderWithQiankun({
        bootstrap,
        mount,
        unmount,
    })
    
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值