先贴一下用到的版本
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.4",
"custom-event-polyfill": "^1.0.7",
"dayjs": "^1.8.28",
"element-ui": "^2.15.6",
"fetch-polyfill": "^0.8.2",
"js-cookie": "^3.0.1",
"js-md5": "^0.7.3",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"qiankun": "^2.3.2",
"vue": "^2.6.12",
"vue-router": "^3.1.5",
"vuex": "^3.1.2",
"whatwg-fetch": "^3.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-plugin-router": "~4.2.0",
"@vue/cli-plugin-vuex": "~4.2.0",
"@vue/cli-service": "~4.2.0",
"compression-webpack-plugin": "^6.1.1",
"gulp": "^5.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-css-wrap": "^0.1.2",
"merge-stream": "^2.0.0",
"node-sass": "^4.12.0",
"pug": "^2.0.3",
"pug-filters": "^3.1.0",
"pug-html-loader": "^1.1.5",
"pug-loader": "^2.4.0",
"pug-plain-loader": "^1.0.0",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.12"
}
一、找不到子应用的入口
[qiankun] You need to export lifecycle functions in vue2 entry
以下是webpack4的解决方案:vue.config.js里设置output
const { name } = require('./package.json')
module.exports = {
devServer: {
host: 'localhost',
hot: true,
port: 8052,
open: true,
injectClient: false,
headers: {
"Access-Control-Allow-Origin": "*", // 必须设置跨域
},
},
configureWebpack: {
output: {
library: `${name}-[name]`, // 名字默认使用package的名字或者自己定义一个
libraryTarget: 'umd', // 格式是 umd
jsonpFunction: `webpackJsonp_${name}`,
}
}
}
如果是webpack5,请降级到webpack4( 看我这微笑的表情MMP,^_^)
二、__webpack_public_path__ is not defind no-undef
解决方案:上一行加/* global __webpack_public_path__:writable */,或者直接eslint禁用都可以
三、在子应用刷新报错:SyntaxError: Unexpected token '<' (at
这个报错可能性比较多,我遇到这个比较奇葩,还以为代码错了,一个一个页面找过来找半天没发现问题。后面发现是publicPath: './'的问题。心碎!!
解决方案:改为publicPath: '/' 或者直接去掉就不报错了,
四、回退找不到id
这是做菜单的时候发现的问题,某一次点了浏览器回退按钮后报了找不到id,如下:
Target container with #sub-container not existed
但平常路由跳转都没有问题,大概步骤如下:
主应用页面 > 子应用页面>主应用页面>回退
当上一个历史记录是子应用的时候就报这个错误
解决方案:全部改为window.history进行跳转,子应用也是。
五、频繁的切换主子应用页面导致报错
报错如下:
Error: [qiankun]: Wrapper element for sub-project is not existed!
解决方案如下:
确认了id的确存在后,经查发现还是和问题4同一个问题,部分页面跳转用的还是router。改为history跳转即可。
六、样式隔离遇到的问题
1、strictStyleIsolation: true 开启严格模式后最大的坑,所有设计到popper的组件都出问题了。因为样式隔离的过于严格,导致插入到body的dom无法获取到子应用的样式或者dom样式的计算出现问题。比如:下拉框丢失绝对定位导致下拉框的dom跑页面最下面去了。
2、experimentalStyleIsolation: true 开启这个处于实验性的隔离模式,哎,也很坑。最大的问题就是很多样式都必须在主应用设置。比如:主应用和子应用都加载了iconfont的链接,但主应用不是最新的一版,子应用是最新版。那主应用就缺少最新的部分icon,当子应用使用这部分新的icon时,你以为会有,但实际上你无法加载,因为主应用那边没有。
3、这俩模式都存在的问题是document在子应用无法使用,因为主子应用共用同一个document。子应用的document就无法使用。平常你自己写的document.querySelector等还可以在render那里定义一个window.parentDocument = props.container以外,其他引入的js文件就很坑了,你得自己去一个一个替换。
七、子应用el-dialog弹框样式丢失的问题
网上找了一大堆,最后决定使用重写document.body.appendChild方法来实现。
参考:https://juejin.cn/post/7102698184496906247
let originFn = document.body.appendChild.bind(document.body)
function render(props = {}) {
const { container } = props
redirectPopup(container)
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/app-slope' : '/',
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes,
});
// console.log('router===>', router)
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#appSlope') : '#appSlope');
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
}
export async function unmount() {
console.log('instance-slope:', instance)
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
document.body.appendChild = originFn
}
function redirectPopup(container){
// 这里需要的是原始的classname,像popper-class自定义的样式名加这里是不起作用的
const whiteList = ['el-dialog__wrapper', 'el-cascader__dropdown', 'el-picker-panel', 'el-select-dropdown']
let originFn = document.body.appendChild.bind(document.body)
document.body.appendChild = (dom) => {
if (intoWhite(whiteList, dom.classList)) {
container.querySelector('#appSlope').appendChild(dom)
} else {
originFn(dom)
}
}
}
function intoWhite(whiteList, classList) {
let isIn = false
classList.forEach(it => {
if (whiteList.includes(it)) {
isIn = true
}
})
return isIn
}
八、样式表加载顺序乱掉了
按照加载顺序,应该是overflow-x:auto;的优先级更高,因为是后面加载,但现在顺序反过来了,说明加载顺序出现了问题;但只有线上环境有问题,本地没有。