qiankun 微前端集成子项目

场景一:常规子应用接入(基于 Umi/Webpack)

在这个场景中,主应用和子应用通常都是基于 UmiJS 或标准的 Webpack 构建。

1. 主应用配置

主应用需要在路由中注册子应用,并在配置文件中指明子应用的真实访问地址(区分开发环境和生产环境)。

路由配置 (routes.ts)

添加子应用的路由匹配规则,注意路径后面的 /* 是必须的:

typescript 复制代码
export default[
  // ...其他路由
  {
    path: '/iocPage/*',
    name: 'ioc大屏',
    layout: false,
    microApp: 'app1', // 这里的 microApp 名字必须与下面 config 中配置的 name 保持一致
    microAppProps: {
      autoSetLoading: true,
    },
  },
];

开发环境配置 (config.develop.ts)

开发环境下,entry 直接指向子应用本地启动的服务地址:

typescript 复制代码
import { defineConfig } from 'umi';

export default defineConfig({
  qiankun: {
    slave: {},
    master: {
      apps:[
        {
          name: 'app1',
          entry: 'http://192.168.2.12:8111' // 子应用本地测试环境地址
        }
      ],
    },
  },
});

生产环境配置 (config.production.ts)

生产环境下,entry 通常指向 Nginx 或后端的代理路径:

typescript 复制代码
import { defineConfig } from 'umi';

export default defineConfig({
  qiankun: {
    slave: {},
    master: {
      apps:[
        {
          name: 'app1',
          entry: '/ioc/'  // 生产环境的后端/Nginx代理路径
        }
      ],
    },
  },
});

访问地址演示: 部署后,通过 http://192.168.2.120:9080/iocPage/home 即可访问该子应用。


2. 子应用(app1)配置

基础配置 (config.ts)

开启 qiankun 插件支持:

typescript 复制代码
import { defineConfig } from 'umi';

export default defineConfig({
  base: '/',
  qiankun: {
    slave: {},
    master: {}
  }
});

生产环境配置 (config.production.ts)

由于生产环境主应用通过 /ioc/ 代理访问子应用资源,因此必须配置 publicPath

typescript 复制代码
import { defineConfig } from 'umi';

export default defineConfig({
  // publicPath 需同主应用 config.production.ts 中的 entry 保持一致
  publicPath: '/ioc/', 
});

项目配置 (package.json)

确保项目名称配置正确,这会作为 qiankun 识别的标识之一:

json 复制代码
{
  "name": "ioc"
}

场景二:Vite 项目作为子应用接入

由于 Vite 默认的 ESM 模块加载方式与 Qiankun 目前基于代码包裹的沙箱机制存在冲突,因此接入 Vite 子应用需要借助 vite-plugin-qiankun 插件。

1. 主应用配置增加 Vite 子应用

与场景一类似,主应用仍需增加路由和应用注册信息。

路由配置:

typescript 复制代码
{
  path: '/policyMatchPage/*',
  name: '政策匹配',
  layout: false,
  microApp: 'app2',
  microAppProps: {
    autoSetLoading: true,
  },
}

主应用注册配置:

typescript 复制代码
qiankun: {
  slave: {},
  master: {
    apps:[
      // ...之前的 app1
      {
        name: 'app2',
        entry: '/policyMatch' // 生产环境后端代理路径
      }
    ],
  },
}

2. Vite 子应用(app2)配置

首先需要安装对应的插件:

bash 复制代码
npm install vite-plugin-qiankun qiankun -S

Vite 构建配置 (vite.config.js)

需要引入插件、配置跨域、并修改 build 产物格式:

javascript 复制代码
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import md from 'vite-plugin-md';
import qiankun from 'vite-plugin-qiankun';

export default defineConfig({
  // 生产环境配置为代理路径,开发环境为 '/'
  base: process.env.NODE_ENV === 'production' ? '/policyMatch/' : '/',
  plugins:[
    vue({
      include: [/\.vue$/, /\.md$/], // 让 Vite 处理 .md 文件
    }),
    md(),
    // 'app2' 必须与主应用注册的 name 一致
    qiankun('app2', { 
      useDevMode: true
    }),
  ],
  server: {
    port: 5173,
    cors: true, // 必须开启跨域,主应用才能动态 fetch 拉取资源
    origin: 'http://localhost:5173',
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  build: {
    rollupOptions: {
      output: {
        format: 'umd' // 配合 qiankun 的模块加载
      }
    }
  },
});

入口文件修改 (main.js)

Vite 子应用不再通过导出生命周期函数的方式,而是通过 renderWithQiankun 进行生命周期的劫持和渲染:

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

let app = null;

function render(props = {}) {
  const { container } = props;
  app = createApp(App);
  app.use(router);
  // 判断是作为子应用挂载到主应用 DOM 内,还是独立运行
  app.mount(container ? container.querySelector('#app') : '#app');
}

// 核心:判断是否在 Qiankun 环境内
if (qiankunWindow.__POWERED_BY_QIANKUN__) {
  renderWithQiankun({
    bootstrap() {
      console.log('===qiankun bootstrap===');
    },
    mount(props) {
      console.log('===qiankun mount===', props);
      render(props);
    },
    unmount(props) {
      console.log('===qiankun unmount===');
      if (app) {
        app.unmount();
        app = null;
      }
    },
    update(props) {
      console.log('===qiankun update===');
    }
  });
} else {
  // 独立运行
  render();
}

路由配置修改 (router.js)

Vue Router 的 history 模式需要根据环境动态设置 base 路径:

javascript 复制代码
import { createRouter, createWebHistory } from "vue-router";
import { qiankunWindow } from "vite-plugin-qiankun/es/helper";
import routes from './routes'; // 你的路由表

const router = createRouter({
  // 当在微前端环境下时,基础路径需设为主应用中配置的路由路径
  history: createWebHistory(
    qiankunWindow.__POWERED_BY_QIANKUN__ ? '/policyMatchPage/' : '/'
  ),
  routes
});

export default router;

💡 总结与避坑指南

  1. 路由与 PublicPath 对应关系 :主应用的路由 Path(例如 /iocPage/*)决定了子应用 Router 的 base;而主应用的 entry 代理地址(例如 /ioc/)决定了子应用构建时的 publicPath 或 Vite 的 base。这两者不要混淆。
  2. Vite 接入的坑 :原生 Qiankun 对 Vite 的支持不完善,千万不要忘了引入 vite-plugin-qiankun 并按需调整入口文件生命周期的写法。
  3. 跨域问题 :子应用的 server 配置中一定要加上 cors: true 以及 Access-Control-Allow-Origin: '*',否则主应用在开发环境下 fetch 子应用资源会报跨域错误。
相关推荐
一颗烂土豆1 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
kyriewen4 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
weedsfly6 小时前
迭代器、生成器与异步迭代——让数据“按需流动”的艺术
前端·javascript
假如让我当三天老蒯7 小时前
前端跨域解决方案(学习用)
前端·javascript·面试
铁皮饭盒8 小时前
Bun 哪比 Node.js 快?
javascript·后端
JieE21216 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
candyTong19 小时前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
_柳青杨1 天前
深入理解 JavaScript 事件循环
前端·javascript
大家的林语冰1 天前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
weedsfly1 天前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript