微前端问题汇总
前⾔
微前端是搭建起来了,但是要⽤起来啊,把原来的⼏个项⽬集成进来的过程遇到问题总结。
零、沙箱设置的简单理解
strictStyleIsolation = false
可以获取到⼦应⽤的dom节点,主应⽤可修改⼦应⽤样式,但是⼦应⽤不可修改主应⽤的样式。需要注意样式不能冲突。strictStyleIsolation = true
样式严格分离,不可获取到⼦应⽤的dom节点。
⼀、vue-cli2搭建的⽼项⽬微应⽤配置
1.1、打包配置:
webpack配置在哪呢
熟读官⽅⽂档发现,打包配置为了让主应⽤能识别⼦应⽤暴露出来的信息,⼦应⽤打包需要进⾏的配置。
关键词:⼦应⽤、打包、暴露
那可不是在⼦应⽤的webpack中配置output,因为run dev和run build都需要对外暴露吧,那就是配置到fig.js咯?打开⼀看果然原来就有output属性。
于是追加
const packageName = require('../package.json').name;
library: `${packageName}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${packageName}`,
即可。
此处注意,官⽅⽂档
require('./package.json').name;,
此处根据项⽬⽂件位置应该是
require('../package.json').name;
多了⼀层
配置正确后,运⾏npm run dev成功启动项⽬。
发现单独访问可以,但是通过主应⽤访问报跨域的错误提⽰。需要查看跨域配置是否正确。
1.2、跨域配置:
你以为在config/index.js下的dev⾥⾯吗?不是的
⽣产环境的跨域是在nginx中进⾏配置,那开发环境的跨域就是在fig.js中咯。
打开⽂件⼀看果然有个devServer属性,于是在其下添加配置项:
headers: {
'Access-Control-Allow-Origin': '*'
},
即可。
1.3、附webpack官⽅⽂档:
⼆、res中⽆法拿到router对象
在js⽂件⽐如axios的返回拦截res中⽆法拿到router对象进⾏路由跳转
挂到原⽣⽅法上即可。
if (!window.__POWERED_BY_QIANKUN__) {
render()
Vue.prototype.$subRouter = router
}
Vue.prototype.$subRouter.push({ name: 'Login', params: { message: ssage } })
引申问题:
此时是独⽴渲染的时候,把路由挂在了原⽣上,但是以⼦应⽤嵌⼊微前端时。
⼦应⽤在请求返回res中得知超时,需要跳转登录界⾯,是⽆法拿到原⽣router的,只能通知主应⽤,进⾏路由跳转。详见⽗⼦应⽤间的监听传值。(下⼀个问题)
三、⽗⼦应⽤通过props传值
问题:
⼦系统登录超时res跳转不了登录界⾯,需要通知主应⽤进⾏跳转。
解决:
建议⽤props传值处理。
主应⽤main.js注册⼦应⽤
{
nginx部署前端项目name: 'XxxSubSystem',
entry: '//10.10.26.197:8091',
container: '#container',
activeRule: '/test/xxx-sub-system',
props: { // 额外参数-⽤于⽗⼦应⽤之间相互调⽤
getToken: () => {
console.log('获取token')
},
reRegister: (message) => {
router.push({ name: 'Login', params: { message: message } })
console.log('重新登录')
}
}
},
⼦应⽤main.js挂载⽅法
function render (props = {}) {
const { container } = props
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/test/xxx-sub-system/' : '/',
mode: 'history',
routes
})
instance = new Vue({
router,
store,
render: h => h(App)
}).$mount(container ? container.querySelector('#app') : '#app')
// 将主应⽤的函数挂到原⽣上⽅便调⽤
Vue.prototype.$baseReRegister = Register
Vue.prototype.$baseGetToken = Token
}
⼦应⽤接⼝返回res/index.js超时拦截
if (errCode === 401) {
if (!window.__POWERED_BY_QIANKUN__) {
Vue.prototype.$subRouter.push({
name: 'Login', params: {
message: ssage
}
})
} else {
Vue.prototype.$ssage)
}
}
四、来回切换⼦应⽤容易崩了
报错:
application ‘SubPhm’ died in status SKIP_BECAUSE_BROKEN: Cannot read property ‘replace’ of undefined 现象:
div=container的节点存在,⼦应⽤挂上去了;
但是加载失败,⼦应⽤挂上了,但是挂了。
原因分析:
来回切换⼦系统的时候,id为container的DOM节点不断的进⾏结构渲染导致的崩溃。
原来⼦应⽤直接挂在app中的div,切换应⽤时,整个dom重新渲染。
改造⽅法:
将⼦应⽤挂到⼦路由下⾯,路由跳转时中的部分肯定是要重新渲染的,所以⼦应⽤切换时,也只是渲染
路由部分,保持了外层不动,减轻浏览器重绘压⼒。
详见下⼀点,如何将⼦应⽤挂在⼦路由下。
五、如何将⼦应⽤挂在⼦路由下
改造前:
主应⽤App.vue
<template>
<div id="app-base">
<router-view v-if="isLoginPage" />
<el-container v-else>
……
<el-container>
……
<div v-if="isSubRoute" id="container" class="base-content"></div>
<router-view class="base-content" />
</el-container>
</el-container>
</div>
</template>
主应⽤router.js
const routes = [
{
path: '/',
name: 'Default',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/app',
name: 'App',
component: App
}
]
主应⽤main.js
{
name: 'SubSystem',
entry: '//IP:PORT',
container: '#container',
activeRule: '/sub-system'
},
⼦应⽤main.js
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/sub-system/' : '/',
mode: 'history',
routes
})
改造后:
主应⽤App.vue
<template>
……
<router-view class="base-content" />
</template>
主应⽤baseSub.vue
<template>
<div id="container"></div>
</template>
主应⽤router.js
const routes = [
{
path: '/',
name: 'Default',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/basesub/*',
name: 'BaseSub',
component: BaseSub,
children: [
]
},
{
path: '/app',
name: 'App',
component: App
}
]
主应⽤main.js
{
name: 'SubSystem',
entry: '//IP:PORT',
container: '#container',
activeRule: '/basesub/sub-system'
},
⼦应⽤main.js
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/ basesub/sub-system/' : '/', mode: 'history',
routes
})
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论