1、需要安装插件:实际开发过程需要其他插件的话,在增加
Vue主引用:dependencies:qiankun
Nuxt子应用:devDependencies(开发依赖):@femessage/nuxt-micro-frontend(需要暴露qiankun方法给主应用调用);dependencies(生产依赖):@nuxtjs/router(需要对nuxt page目录下的路由重写)
2、vue-cli 脚手架搭建主应用;
需要在入口main.js中引入乾添加
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import store from './store'
import { registerMicroApps, start } from 'qiankun'
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
/*
注册子应用
registerMicroApps(apps, lifeCycles)
apps: 必填,子应用注册的信息
lifeCycles: 全局微应用生命周期钩子
*/
registerMicroApps(
[
{
name: 'vueApp',
entry: 'http://localhost:8081',
container: '#vue-child', // 渲染微应用的容器节点
activeRule: '/app-vue', // 微应用的激活规则,路由匹配到/app-vue时,加载子应用
props: { // 父传子
values: '123213'
// routerBase: '' // 设置子应用的基础路由
}
},
{
name: 'polNuxtApp', // 微应用名称,确保唯一
entry: 'http://localhost:3000', // 子应用的地址 微应用的入口; 在nuxt.config.js中引用的静态资源需要跨域;需要配置Nginx; 参考:https://segmentfault.com/a/1190000012550346
container: '#pol-nuxt-child', // 渲染微应用的容器节点
activeRule: '/pol-app-nuxt', // 微应用的激活规则,路由匹配到/pol-app-nuxt时,加载子应用
props: { // 父传子
// default: 默认主题 dark:暗黑主题
theme: 'dark'
}
}
],
{
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)
}
]
}
)
// 设置主应用启动后默认进入的微应用
// setDefaultMountApp('/app-vue')
// 启动 qiankun
start()
添加id容器去加载子应用:
<div id="pol-nuxt-child" style="height:1080px"> <!-- 子应用内用 --> </div>
3、Nuxt 子应用的配置
配置nuxt.config.js文件:buildModules 中引入@nuxtjs/router;modules中引入@femessage/nuxt-micro-frontend;增加mfe.js 暴露乾坤;
buildModules: [
// Doc: https://github.com/nuxt-community/eslint-module
'@nuxtjs/eslint-module',
[
'@nuxtjs/router',
{ keepDefaultRouter: true, path: './router', fileName: 'index.js' }
]
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
// See https://axios.nuxtjs.org/options
['@nuxtjs/axios', {
proxy: true
}],
'@femessage/nuxt-micro-frontend'
],
// 暴露乾坤
MFE: {
force: true
},
增加mef.js;文件目录跟nuxt.config.js同级
export default function (render) {
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
}
export function bootstrap () {
console.log('bootstrap')
}
export async function mount (render, props) {
console.log('mount-----')
await render()
}
export async function update () {
await console.log('update-----')
}
export function mounted (instance, props) {
// 主应用传值操作
localStorage.setItem('theme', props.theme)
console.log('nuxt--子应用', props)
}
export function beforeUnmount (instance) {
console.log('beforeUnmount-----')
}
export function unmount () {
console.log('unmount-----')
}
新增router重写路由;通过window.__POWERED_BY_QIANKUN__ 去加载主应用的基础路由;
注意事项:对嵌套路由和动态路由处理,动态路由处理必须加上‘.vue’文件后缀;
const qkBaseRoute = window.__POWERED_BY_QIANKUN__ ? '/pol-app-nuxt' : ''
import Router from 'vue-router'
import qkCofing from '@/qkCofing.js'
// 当前默认路由放置到自定义路由
export function createRouter (ssrContext, createDefaultRouter, routerOptions) {
let options
routerOptions ? options = routerOptions : options = createDefaultRouter(ssrContext).options
return new Router({
...options,
mode: 'history',
routes: setBaseRouter(options.routes)
})
}
function dynamicImport (path) {
const curPath = setDynamicRoute(path)
return import(`~/pages${curPath}`).then(m => m.default || m)
}
const resolveRoute = route => ({
...route,
path: `${qkCofing.qkBaseRoute}${route.path}`,
component: () => dynamicImport(route.path)
})
function setBaseRouter (routes) {
return routes.map(route => ({
...resolveRoute(route),
children: route.children ? setNestRoute(route).map(resolveRoute) : []
}))
}
// 处理嵌套路由
function setNestRoute (route) {
const curIndex = route.path.lastIndexOf('/')
const curStr = route.path.substring(curIndex + 1, route.path.length)
route.children.map(item => {
item.path ? item.path = `${route.path}/${item.path}` : item.path = `${route.path}/${curStr}`
})
return route.children
}
// 处理动态路由
function setDynamicRoute (path) {
let curPath = path
if (path.includes(':') && path.includes('?')) {
curPath = curPath.replace(':', '_').replace('?', '.vue')
}
return curPath
}
注意事项:
1、nuxt.config.js: script、link引入的静态文件需要配置ngnix跨域;参考:Nginx配置跨域请求 Access-Control-Allow-Origin * - SegmentFault 思否
2、子应用开发过程中调用服务端代理问题:
除子应用需要代理外
主应用也需要设置代理
3、子应用中通过ifream 嵌入的系统,能正常使用;
4、本地存储:主应用和子应用是共享的;
5、对嵌套路由和动态路由处理,动态路由处理必须加上‘.vue’文件后缀;