为了项目不同模块的耦合度降低,方便开发人员后续的开发,降低代码维护的成本,方便项目管理。因此,调研了微前端框架 qiankun。 本demo主应用使用了taro框架的vue2.x版本,微应用使用了vue2.x脚手架快速搭建。
一、改造主应用
1、qiankun框架的引入:
yarn add qiankun # 或者 npm i qiankun -S
2、注册微应用:
//app.ts
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'vueApp',
entry: '//localhost:8080',
container: '#container',
activeRule: '/#/pages/test/test',
},
]);
3、新建页面并声明路由
//pages/test/test.vue
<template>
<div>
<div id="container"></div>
</div>
</template>
<script>
import { start } from 'qiankun';
export default {
data(){
return{
}
},
mounted(){
if (!window.qiankunStarted) {
window.qiankunStarted = true;
start({
sandbox:true
});
}
//当主服务跳转到当前页面时,重定向到微应用home页面
Taro.navigateTo({ url:'pages/test/test/home'})
}
}
</script>
//app.config.ts
export default {
pages: [
pages/test/test,
]
}
二、搭建微应用
使用了vue2.x框架快速搭建一个微应用项目
1、创建vue2项目
vue init webpack demo
2、改造微应用的main.js文件,将bootstrap、mount、unmount三个钩子函数暴露给主应用使用
//main.js
import './public-path';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
Vue.config.productionTip = false;
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/pages/test/test/' : '/',
mode: 'hash',
routes,
});
const VueRouterPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (to) {
return VueRouterPush.call(this, to).catch(err => err)
}
instance = new Vue({
name: 'vueApp',
router,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#vueApp') : '#vueApp');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('bootstrap');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
}
export async function unmount() {
console.log('unmount');
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
//public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
3、注册firstPage和home两个微应用页面
//router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import childContainer from '@/components/childContainer.vue'
import home from '../pages/home/home.vue';
import firstPage from '../pages/firstPage/firstPage.vue';
Vue.use(Router)
const routes = [
{
path: '/pages/test/test',
name: 'childContainer',
component: childContainer,
children:[
{
path: '/pages/test/test/home',
name: 'home',
component: home
},
{
path: '/pages/test/test/firstPage',
name: 'firstPage',
component: firstPage
},
]
},
]
export default routes
//components/childContainer.vue;
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods:{
}
}
</script>
//pages/home/home.vue
<template>
<div>
<div @click="goto_pages">home页面</div>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods:{
goto_pages(){
this.$router.push('/pages/test/test/firstPage')
}
}
}
</script>
//pages/firstPage/firstPage.vue
<template>
<div>
<div @click="goto_pages">firstPage页面</div>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods:{
goto_pages(){
this.$router.push('/pages/test/test/home')
}
}
}
</script>
4、改造webpack配置文件
//build/webpack.base.conf.js
const { name } = require('../package');
//替换output
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath,
library: `${name}-[name]`,
libraryTarget: 'umd', // 把微应用打包成 umd 库格式
jsonpFunction: `webpackJsonp_${name}`,
},
//webpack.dev.conf.js
devServer:{
//添加下面代码
headers: {
'Access-Control-Allow-Origin': '*',
},
}
qiankun 框架实践问题总结
- 微应用打包后,当微应用项目中的图片资源过大时,主应用访问微应用时,会加载不出来(可以使用外链的方式引入图片)
- 部署微应用时,需要在nginx上配置跨域
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
- 主应用储存的localStroage,微应用可以拿到
- 主服务传值给微服务,可以采取qiankun框架中的通讯池模式
- 当使用微信打来项目时,会出现头部的导航头,用其他浏览器打开,则没有
- 微服务必须是在主应用的某个页面的mounted生命周期上挂载,不能挂载到app.js中
- 在微应用路径下刷新,404问题,让微应用的base和主应用挂在微应用的页面路由保持一致
- 微应用跳转到主应用其他页面可以使用window.history.pushState()方法,并刷新页面,才能正常跳转过去。
window.history.pushState({ msg:'你好' }, '',`#/pages/ha/test02/test02`)
location.reload();
- 在微应用除首页外,刷新页面,将会跳转到微应用首页
- 注意:如果需要引入css预编译器,请安装正确的版本,最新版本和webpack不兼容,会导致安装报错。