微前端乾坤框架的实际应用

2023-08-24  本文已影响0人  张晓畅

上来就干货!

主应用(基座)

h5_config.js 配置(引入到index.html)

window.SITE_CONFIG = {};
window.SITE_CONFIG['appName'] = '微前端‘;
window.SITE_CONFIG['storeState'] = {} // vuex本地储存初始化状态(用于不刷新页面的情况下,也能重置初始化项目中所有状态)

//微应用
window.MicroPre = 'http://127.0.0.1'
window.microApps = [
    // 子应用1
    {
        name: 'subApp1',
        entry: MicroPre+':8001/',
        container: '#micro-app',
        activeRule: '/subapp1',
    },
    // 子应用2
    {
        name: 'subApp2',
        entry: MicroPre+':8002/',
        container: '#micro-app',
        activeRule: '/subapp2',
    },
]

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import http from '@/utils/request'
import cloneDeep from 'lodash/cloneDeep'

//==========================微前端=====start
import { registerMicroApps, start, addGlobalUncaughtErrorHandler } from 'qiankun';
// 子应用
window.microApps = window.microApps.map(item=>{
  item.props = {
    microData:{
      entry:item.entry,
      parentStore:store,
      parentRouter:router,
      ProjectData: '额外参数'
    }
  }
  return item;
})
registerMicroApps(window.microApps,{
  beforeLoad: (app) => {
    store.commit("qiankunFinish",true);
    console.log('beforeLoad, 子应用注册:', app.name)
  },
  beforeMount: (app) => {
    console.log('beforeMount,子应用挂载前:', app.name)
  },
  afterMount: (app) => {
    store.commit("qiankunFinish",false);
    console.log('afterMount,子应用挂载:', app.name)
  },
  beforeUnmount:(app)=>{
    store.commit("qiankunFinish",true);
    console.log('beforeUnmount,子应用卸载前:', app.name)
  },
  afterUnmount: (app) =>{
    store.commit("qiankunFinish",false);
    console.log("afterUnmount,卸载后", app.name)
  },

});

addGlobalUncaughtErrorHandler(e => {
  console.log('qk error:', e)
  const {message: msg} =e
  if(msg&&msg.includes('died in status LOADING_SOURCE_CODE')){
    console.log('微应用加载失败, 请检查应用是否可用')
  }
})

start({prefetch:true});
//==========================微前端=====end

Vue.config.productionTip = false

// 挂载全局
Vue.prototype.$http = http

// 保存整站vuex本地储存初始状态
window.SITE_CONFIG['storeState'] = cloneDeep(store.state)
// 主应用(基座)
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#micro-service')

子应用

创建public-path

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

创建qiankun.js

import './public-path'; // 微前端路径
import Vue from 'vue';
import Router from 'vue-router'
import Cookies from 'js-cookie'
import http from '@/utils/request'

Vue.config.productionTip = false

Vue.use(Router);

// 挂载全局
Vue.prototype.$http = http

/**
 * 
 * @param {*} App 
 * @param {*} store 
 * @param {*} setting 微服务配置
 * @param {*} projectFiles 文件夹下的路由
 * @param {*} otherRoutes :各自项目自定义的路由
 * @returns 
 */
export default function qiankun(App, store, setting, projectFiles,otherRoutes=[]){
    let instance = ''
    let router = ''
    const isQiankun = !!window.__POWERED_BY_QIANKUN__;//当前是微
    function render(props={}) {
        const { container } = props;
        const defaultRoutes =  [...otherRoutes];
        router = new Router({
            base: isQiankun ? `/${setting.QIANKUN_APP_NAME}` : setting[process.env.NODE_ENV],
            mode: 'history',
            scrollBehavior: () => ({ y: 0 }),
            routes:defaultRoutes
        })
          
        Vue.config.performance = process.env.NODE_ENV === 'development';
        instance = new Vue({
            router,
            store,
            render: h => h(App)
        }).$mount(container ? container.querySelector(`#${setting.QIANKUN_APP_NAME}`) : `#${setting.QIANKUN_APP_NAME}`);
    }
    
    // 微前端钩子
    async function bootstrap() {
        console.log('[vue] 微应用初始化时调用一次');
    }
    async function mount(props) {
        const microData = props.microData;
        window.entry = microData.entry || "";
        window.ProjectData = microData.ProjectData;
        window.parentStore = microData.parentStore;
        window.parentRouter = microData.parentRouter;
        console.log(window.parentStore)
        console.log('[vue] 应用每次进入都会触发渲染', props);
        let token = window.parentStore.state.token
        token && Cookies.set('token', window.parentStore.state.token)
        render(props);
    }
    async function unmount() {
        console.log('[vue] 应用每次切出/卸载都会触发');
        instance.$destroy();
        instance.$el.innerHTML = '';
        instance = null;
        router = null;
        window.SITE_CONFIG['dynamicMenuRoutesHasAdded'] = false;
        console.log('销毁成功')
    }
    return {render, bootstrap, mount, unmount}
}

setting.js 配置

module.exports = {
    QIANKUN_APP_NAME: "subApp1",// 子应用的名称
    production: '/child/subApp1/', // 生产环境打包路径(根据实际部署环境配置)
    devlopment: './', // 本地运行路径
}

main.js

import Vue from 'vue';
import App from './App'
import * as directiverData from '@/utils/directive';
import store from './store'
import qiankun from '@/qiankun'

import cloneDeep from 'lodash/cloneDeep'

for(let name in directiverData){
    Vue.directive(name,{inserted:directiverData[name]});
}

const setting = require('./setting.js')

window.SITE_CONFIG['storeState'] = cloneDeep(store.state)

Vue.prototype.$setting = setting
const projectFiles = require.context('./views', true, /\.vue$/).keys()
const init = qiankun(App, store, setting, projectFiles)

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
    console.log('独立')
    init.render();
}

// 抛出乾坤钩子
export const {bootstrap,mount,unmount} = init;
上一篇 下一篇

猜你喜欢

热点阅读