qiankun.js 使用总结

98 阅读2分钟

写在前面

在做大数据商业化项目时,项目比较多,使用的是iframe嵌套方式。使用上没有问题,在使用体验上可以说很难受,弹框遮罩,复制url链接时,定位不到页面等等吧,所以重构使用了qiankun,以下是使用体验,大家多多指点

1.使用

qiankun官网

安装

    npm i qiankun -S

父应用里使用,注册子应用

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react-app',
    entry: '//localhost:3000',
    container: '#react-app',
    activeRule: '/react-app',
  },
  {
    name: 'vue-app',
    entry: '//localhost:8080',
    container: '#vue-app',
    activeRule: '/vue-app'
  },
]);

start();

子应用导出相应勾子

/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log('react app bootstraped');
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
let instance
export async function mount(props) {
  // react
  ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));

  // vue 
  instance = new Vue({
    router,
    store,
    render: h => h(App),
  })
  instance.$mount(container ? container.querySelector('#app') : '#app');
}

/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props) {
  // react
  ReactDOM.unmountComponentAtNode(
    props.container ? props.container.querySelector('#root') : document.getElementById('root'),
  );

  // vue
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null
}

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
  console.log('update props', props);
}

webpack 配置

publicPath: VUE_APP_NAME ? `/${VUE_APP_NAME}` : '/',
configureWebpack: config => {
    return {
        output: {
          library: VUE_APP_NAME,
          libraryTarget: 'umd',// 把微应用打包成 umd 库格式
          jsonpFunction: `webpackJsonp_${VUE_APP_NAME}`,
        }
    }
}

此时项目就可以跑起来调试了

遇到的问题

css样式冲突问题

解决办法: 可以在每个子应用加个唯一的命名空间,忽略掉常用的组件样式

css: {
    loaderOptions: {
      postcss: {
        plugins: [
          // 自己写的插件
          require('postcss-namespace')(`.${VUE_APP_NAME}`, {
            // 忽略掉 element-ui 的样式,bodyhtml, *
            ignore: [/^.el\-/, 'body', 'html', '*'],
          }),
        ],
      },
    },
  }

主应用svg样式 影响到子应用

区分href id

菜单高亮问题

比如路由 /app/list /app/detail 从列表进入到详情时,菜单高亮无问题,但是留在详情时,刷新页面会不显示高亮菜单

子应用资源加载路径问题

当publicPath 配置没问题也会导致一些资源加载有问题, 比如,element-ui 加载的一些字体图标文件,或者css里引入了一些相对路径文件,将这些资源转为绝对路径

chainWebpack: config => {
    // 字体图标路径
      config.module
          .rule("fonts")
          .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/)
          .use("url-loader")
          .loader("url-loader")
          .options({
              limit: 0,
              name: 'static/fonts/[name].[chunkhash:8].[ext]',
              publicPath: process.env.NODE_ENV === 'production' ? `/${VUE_APP_NAME}` : '',
          });
      // 图片的相对路径改为绝对路径
      config.module
          .rule("images")
          .test(/\.(png|jpe?g|gif|webp|ico)(\?.*)?$/)
          .use("url-loader")
          .loader("url-loader")
          .options({
              limit: 0,
              // name 代表 url-loader 会将资源写到 static/fonts/ 下
              name: 'static/img/[name].[chunkhash:8].[ext]',
              // publicPath 代表资源引入 url 会生成 /agilebi 的前缀,比如 /VUE_APP_NAME/static/img/bg_header.790a94f4.png
              publicPath: process.env.NODE_ENV === 'production' ? `/${VUE_APP_NAME}` : '',
          });
}

未完 待续