qiankun + vue3使用踩坑记录

qiankun + vue3使用踩坑记录

1、主应用

vue create qiankun-base
npm install vue-router@4
npm i qiankun -S
  1. 在main.js中引入qiankun
import { registerMicroApps,runAfterFirstMounted,addGlobalUncaughtErrorHandler } from 'qiankun';
registerMicroApps( [{
      name: 'app1',
      entry: 'http://localhost:8081/',
      container: '#container',
      activeRule:'app1'
    }], {
		beforeLoad: [app => {
			return Promise.resolve();
		}]
	}
)
runAfterFirstMounted(() => {
  console.log('子应用加载完毕')
})
/**
 2. 补取异常
 */
 addGlobalUncaughtErrorHandler((event) => {
  const { message } = event;
  // 加载失败时提示
  if (message && message .includes("died in status LOADING_SOURCE_CODE")) {
   console.log("微应用加载失败_"+msg);
  }
});
  1. 在app.vue中添加容器
<div id="container"></div>
  1. 在需要使用的页面添加qiankun启动代码
onMounted(() => {
      if (!window.qiankunStarted) {
        window.qiankunStarted = true;
        start({
            prefetch: true, // 开启预加载
          sandbox: {
            experimentalStyleIsolation: true,
          },
        });
      }
    });
)

补充:想要主应用访问子应用中的某一个页面,代码做出以下修改

  1. main.js里修改activeRule,如果需要访问其他页面,需要新增一个入口
registerMicroApps( [{
      name: 'app1',
      entry: 'http://localhost:8081/',
      container: '#container',
      activeRule:'app1/login' // 访问子应用的login页面
    }], {
		beforeLoad: [app => {
			return Promise.resolve();
		}]
	}
)
  1. 在router里面做出以下添加
{
	path: '/app1/:pathMatch(.*)',
	name: 'app1',
	component: () => import('../views/qiankunEntry.vue'),
}
  1. 新增qiankunEntry.vue
<template>
	<div id="container"></div>
</template>
<script>
import { start } from 'qiankun';
import { reactive, toRefs, ref, onMounted  } from "vue";
export default {
	setup() {
		onMounted(() => {
			start({
				prefetch: false, // 开启预加载
				sandbox: {
					experimentalStyleIsolation: true,
				}
			});
		})
	}
}
</script>

提示:补充的2、3步来设置容器使用更方便,不用考虑样式对#container的影响,也可以避免不需要加载子应用时#container对于已有页面造成影响

注意:这里的container不能添加在启动的页面会报错:Target container with #container not existed while son loading!
特别注意:这里的路由要用createWebHistory,要不然会导致qiankun不能启动!


2、子应用:

提示:子应用不需要安装qiankun

vue create qiankun-app
npm install vue-router@4
  1. 在src目录下面新增public-path.js
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

注意:这里需要在package.json下面新增配置globals

"eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "@babel/eslint-parser"
    },
    "rules": {},
	"globals": {
		"__webpack_public_path__": true
	}
  }
  1. 修改router,直接export default routes,将注册放到main.js中
    注意:要注意这里routes写法,上会报错:Loading chunk src_views_homeView_vue failed.
const routes = [{
    path: '/',
    name: 'homeView',
    component: import('../views/homeView.vue')
  }]

这样是不对的,需要用下面这种写法

import homeView from '../views/homeView.vue'
const routes = [{
    path: '/',
    name: 'homeView',
    component: homeView
  }]

可能跟vue3的路由加载机制有关

  1. 在main.js中添加
import {
	createRouter,
	createWebHistory
} from 'vue-router';
import routes from './router'
let router = null;
let instance = null;
let history = null;

function render(props = {}) {
	const {
		container
	} = props;
	history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? `${props.name}` : '/');
	router = createRouter({
		history,
		routes,
	});
	instance = createApp(App);
	instance.use(router);
	instance.mount(container ? container.querySelector('#app') : '#app');
}

// 本地调试
if (!window.__POWERED_BY_QIANKUN__) {
	render()
}


// 生命周期 - 挂载前,在这里由主应用传过来的参数
export async function bootstrap() {

	// console.log('one bootstrap'+JSON.stringify(props))
	console.log(localStorage.getItem('test'));

}

// 生命周期 - 挂载后
export async function mount(props) {
	render(props)
	// // 主应用传递过来的 props.fn 是一个对象。循环遍历下,将各个属性绑定到子应用的原型链上
	// Object.keys(props.fn).forEach(method => {
	//     createApp.prototype[`$${method}`] = props.fn[method]
	// })
	// 渲染

}

// 生命周期 - 解除挂载
export async function unmount() {
	instance.unmount();
	instance._container.innerHTML = '';
	instance = null;
	router = null;
	history.destroy();
}
  1. 在vue.config.js中
const { name } = require('./package.json')
module.exports = {
  devServer: {
    port: 8081,
    headers: {
      'Access-Control-Allow-Origin': '*'
    }, proxy: {
      '/api4': {
        target: 'http://127.0.0.1',
        changeOrigin: true,
        ws: true,
        pathRewrite: { '^/api4': '' }
      }
    }
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      // 把子应用打包成umd库格式
      // 当我们把 libraryTarget 设置为 umd 后,我们的 library 就暴露为所有的模块定义下都可运行的方式		了,主应用就可以获取到微应用的生命周期钩子函数了
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${name}`
    }
  }
}

使用createWebHistory路由模式的时候会有页面刷新报错的问题,可以在vue.config.js中设置publicPath

publicPath: process.env.NODE_ENV === 'development' ? '/' : '/',

参考链接: vue3.0+乾坤实现微应用
打包发布的部分还没有测试,后续继续补充

你可能感兴趣的:(vue.js,前端,前端框架)