记录qiankun微应用遇到的问题

 先贴一下用到的版本

  "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;的优先级更高,因为是后面加载,但现在顺序反过来了,说明加载顺序出现了问题;但只有线上环境有问题,本地没有。

九、先写这些,后面遇到再加

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值