采用阿里的qiankun实现微前端快速构建
1.利用vue-cli快速构建一个基础项目(基础项目也可以不用vue,这里是为了快速构建采用vue项目作为基础项目)
vue init webpack
npm install
2.下载qiankun
npm install qiankun
3.修改主入口index.html的id,改为container,防止和其他重复
image.png
4.修改main.js ,APP.vue
<template>
<div id="container">
<!-- loading -->
<div v-if="loading">loading</div>
<!-- 子应用盒子 -->
<div id="root-view" class="app-view-box" v-html="content"></div>
</div>
</template>
<script>
export default {
name: 'App',
props: {
loading: Boolean,
content: String
}
}
</script>
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import { registerMicroApps, setDefaultMountApp, start } from 'qiankun'
const router = []
Vue.use(VueRouter)
Vue.config.productionTip = false
let app = null
/**
* 渲染函数
* appContent 子应用html内容
* loading 子应用加载效果,可选
*/
function render ({ appContent, loading } = {}) {
if (!app) {
app = new Vue({
el: '#container',
router,
data () {
return {
content: appContent,
loading
}
},
render (h) {
return h(App, {
props: {
content: this.content,
loading: this.loading
}
})
}
})
} else {
app.content = appContent
app.loading = loading
}
}
/**
* 路由监听
* @param {*} routerPrefix 前缀
*/
function genActiveRule (routerPrefix) {
return location => location.pathname.startsWith(routerPrefix)
}
function initApp () {
render({ appContent: '', loading: true })
}
initApp()
// 传入子应用的数据
let msg = {
data: {
auth: false
},
fns: [
{
name: '_LOGIN',
_LOGIN (data) {
console.log(`父应用返回信息${data}`)
}
}
]
}
// 注册子应用
registerMicroApps(
[
{
name: 'vue',
entry: '//localhost:7101',
render,
activeRule: genActiveRule('/vue'),
props: msg
}
// {
// name: 'sub-app-2',
// entry: '//localhost:8092',
// render,
// activeRule: genActiveRule('/app2')
// }
],
{
beforeLoad: [
app => {
console.log('before load', app)
}
], // 挂载前回调
beforeMount: [
app => {
console.log('before mount', app)
}
], // 挂载后回调
afterUnmount: [
app => {
console.log('after unload', app)
}
] // 卸载后回调
}
)
// 设置默认子应用,与 genActiveRule中的参数保持一致
setDefaultMountApp('/vue')
// 启动
start()
去目录下构建一个vue项目
修改新建项目的vue-config,记得这块端口需要和上面对应
const path = require('path');
const { name } = require('./package');
function resolve(dir) {
return path.join(__dirname, dir);
}
const port = 7101; // dev port
module.exports = {
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
outputDir: 'dist',
assetsDir: 'static',
filenameHashing: true,
// tweak internal webpack configuration.
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
devServer: {
// host: '0.0.0.0',
hot: true,
disableHostCheck: true,
port,
overlay: {
warnings: false,
errors: true,
},
headers: {
'Access-Control-Allow-Origin': '*',
},
},
// 自定义webpack配置
configureWebpack: {
resolve: {
alias: {
'@': resolve('src'),
},
},
output: {
// 把子应用打包成 umd 库格式
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
},
},
};
image.png
在子项目中修改main.js 和追加public-path.js文件,里面有一些和主应用通信的方法
import './public-path';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';
Vue.config.productionTip = false;
Vue.use(ElementUI);
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
mode: 'history',
routes,
});
instance = new Vue({
router,
store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
if (!window.__POWERED_BY_QIANKUN__) {
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,
},
});
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
storeTest(props);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
现在,子项目启动,再将主项目启动就可以了
为了以后脚本方便维护
可以加入 npm-run-all
"start": "npm-run-all start:* ",
"start:angluar": "cd angluar && start cmd /k npm start",
"start:vue": "cd vue && start cmd /k npm start "
install,build同理加入
未来也可以加入react,angluar,jq等作为子应用
参考: https://qiankun.umijs.org/zh/guide
网友评论