基于vue2+qiankun的微前端实现

由于主应用微应用都能做到技术栈无关,不论是 React/Vue/Angular/JQuery 还是其他等框架,这里使用的主应用微应用均使用vue2,前端路由模式为hash模式。

1.主应用下载qiankun
npm i qiankun -S
2.在主应用src文件夹下创建main-app.js

以下micorApps就是子应用,可以配置多个子应用,但是子应用挂载的div是相同的,记住这个  container: '#test-web'

const microApps = [
    {
        name: 'test-web', // 子应用名称
        entry: 'http://localhost:8088/', //子应用运行地址
        activeRule: '#/test-web',//匹配的路由 hash模式前加 # history模式不用加 
        singular: true, // 启用单实例模式
    },
]
 
const apps = microApps.map(item => {
    return {
        ...item,
        container: '#test-web', // 子应用挂载的div
        props: {
            routerBase: item.activeRule // 下发基础路由
        }
    }
})
 
export default apps
3.在主应用main.js中导入main-app.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
import { registerMicroApps, start } from 'qiankun';
import mainApp from './main-app'
registerMicroApps(mainApp, {
  beforeLoad: app => {
    console.log('before load app.name====>>>>>', app.name)
  },
  beforeMount: [
    app => {
      console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name)
    }
  ],
  afterMount: [
    app => {
      console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name)
    }
  ],
  afterUnmount: [
    app => {
      console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name)
    }
  ]
})
start()
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
4.配置主应用路由

在主应用src文件夹下添加qiankun文件夹,并且添加index.vue文件作为入口文件

注意!!!这里的id:test-web要和main-app.js中 container: '#test-web', 名字一致,不然报错

<template>
  <div id="test-web"></div>
</template>
 
<script>
export default {
  mounted() {},
};
</script>
<style scoped>
#test-web {
  width: 100%;
  height: 100%;
}
/* 定义qiankun高为100%,不然的话高度不匹配 */
/deep/ #__qiankun_microapp_wrapper_for_test_web__{
  height: 100%;
}
</style>

在router文件夹下注册qiankun路由

注意!!path: "/test-web/*",路由的名字要和上面的 activeRule:名字一致

import layout from '../qiankun/index.vue'
import Vue from "vue";
import VueRouter from 'vue-router'
import layout from '../qiankun/index.vue'
Vue.use(VueRouter)

const routes = [
    {
      path: "*",
      name: "404",
      redirect: "/404"
    },
    {
      path: "/",
      name: "Login",
      redirect: "/login"
    },
    {
      path: "/login",
      name: "Login",
      meta: { title: "登录" },
      component: () => import("../components/Login")
    },
    {
      path: "/test-web/*",
      meta: 'test-web',
      component: layout
    },
]

const router = new VueRouter ({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})

export default router;
   

到此主应用程序配置完毕

5.在子应用main.js文件添加如下代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
 
Vue.config.productionTip = false
 
// new Vue({
//   router,
//   store,
//   render: h => h(App)
// }).$mount('#app')
 
 
// 判断是否在qiankun的运行环境下,非qiankun运行环境下单独运行
if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
 
let instance = null;
function render(props = {}) {
  const { container } = props;
  console.log(11111111111111, window.__POWERED_BY_QIANKUN__, '字段值')
  instance = new Vue({
    router,
    store,
    render: h => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app', true); //开启沙箱
}
export default instance
if (!window.__POWERED_BY_QIANKUN__) {
  console.log('独立运行')
  render();
}
 
 
function storeTest(props) {
  props.onGlobalStateChange &&
    props.onGlobalStateChange(
      (value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
      true,
    );
  props.setGlobalState &&
    props.setGlobalState({
      ignore: props.name,
      user: {
        name: props.name,
      },
    });
}
 
// 各个生命周期,只会在微应用初始化的时候调用一次,下次进入微应用重新进入是会直接调用mount钩子,不会再重复调用bootstrap
export async function bootstrap() {
  console.log('111111111111 [vue] vue app bootstraped');
}
// 应用每次进入都会调用mount方法,通常在这里触发应用的渲染方法
export async function mount(props) {
  console.log('11111111111 [vue] props from main framework', props);
  storeTest(props);
  render(props);
}
// 应用每次切除/注销会调用的方法,在这里会注销微应用的应用实例
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
}
6.注册子应用路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
 
Vue.use(VueRouter)
 
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  },
  {
    path: "/test-web/nenergyOperation/teamManage/personnelManage",
    name: "人员管理",
    meta: { title: "人员管理" },
    component: () => import("@/views/nenergyOperation/teamManage/personnelManage")
  },
]
 
const router = new VueRouter ({
    mode: 'hash',
    base: window.__POWERED_BY_QIANKUN__ ? '/test-web/' : '/',
    routes
})
 
export default router

注意!!path: "/test-web/nenergyOperation/teamManage/personnelManage"

在你的子应用路由路径前面添加 /test-web,不然主应用跳转微应用的时候找不到路径

7.在子应用webpack.base.conf.js文件里面配置
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {   //编译打包的入口文件  main.js
    app: './src/main.js'
  },  
  output: {    //出口文件

    // 以下三行是为qiankun框架配置
    library: 'test-web',  //这个'test-web'名称必须与主应用main-app.js文件里面配置的子应用名称一致,不然会报错!!
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${name}`,
    
    path: config.build.assetsRoot,  //
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  }
}

这边需要注意!webpack版本5.0以下改为:jsonpFunction: `webpackJsonp_${name}`

webpack5.0以上: chunkLoadingGlobal: `webpackJsonp_${name}`

library: 'test-web',  //这个'test-web'名称必须与主应用main-app.js文件里面配置的子应用名称一致,不然会报错!!

运行端口8081要和主应用配置mian-app.js文件的 entry: 'http://localhost:8081/', //子应用运行地址一致,不然获取不到子应用内容

8.在子应用webpack.dev.conf.js文件中配置
devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin. 打开不运行在src下
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    },
    headers:{'Access-Control-Allow-Origin':'*'}   //*开发环境下解决qiankun跨域问题*
  },

headers:{'Access-Control-Allow-Origin':'*'}   //*开发环境下解决qiankun跨域问题*

到这里就结束了,此时运行主应用跳转路由就跳转到子应用了,在子应用做更改主应用同时就会更新,并且主应用与子应用分别独立开发,独立部署,实现微前端开发。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值