好的,我们来详细说明基于 qiankun 的 Vue 微前端实战方案,涵盖主应用搭建、子应用接入、主-子应用通信和样式隔离。


1. 主应用搭建

核心功能:注册、加载和管理子应用。

1.1 安装依赖
npm install qiankun -S

1.2 主应用入口 (main.js)
import { registerMicroApps, start } from 'qiankun';

// 注册子应用
registerMicroApps([
  {
    name: 'vue-sub-app', // 子应用名称(唯一标识)
    entry: '//localhost:7101', // 子应用入口(开发环境地址或线上URL)
    container: '#subapp-container', // 挂载容器(主应用中的DOM ID)
    activeRule: '/sub-app', // 激活规则(路由前缀)
  },
]);

// 启动 qiankun
start();

1.3 主应用路由配置 (router.js)
import VueRouter from 'vue-router';

const routes = [
  {
    path: '/',
    component: () => import('@/views/Home.vue'),
  },
  // 预留子应用路由(无需具体配置,qiankun 会自动接管)
  { path: '/sub-app*', name: 'SubApp' },
];

const router = new VueRouter({ mode: 'history', routes });

1.4 主应用挂载容器 (App.vue)
<template>
  <div id="app">
    <router-view />
    <!-- 子应用挂载点 -->
    <div id="subapp-container"></div>
  </div>
</template>


2. 子应用接入

核心要求:暴露生命周期钩子,支持独立运行和嵌入主应用。

2.1 修改入口文件 (main.js)
import Vue from 'vue';
import App from './App.vue';
import router from './router';

let instance = null;

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

// 独立运行时直接渲染
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// 暴露生命周期钩子
export async function bootstrap() {}
export async function mount(props) {
  render(props);
}
export async function unmount() {
  instance.$destroy();
}

2.2 修改打包配置 (vue.config.js)
const { name } = require('./package.json');

module.exports = {
  devServer: {
    port: 7101, // 与主应用注册的entry端口一致
    headers: {
      'Access-Control-Allow-Origin': '*', // 允许跨域
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 将子应用暴露为UMD模块
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};


3. 主-子应用通信

方案:使用 qiankun 提供的 initGlobalState 实现状态共享。

3.1 主应用初始化全局状态 (main.js)
import { initGlobalState } from 'qiankun';

// 初始化状态
const actions = initGlobalState({ user: { name: 'Admin' } });

// 监听子应用状态变更
actions.onGlobalStateChange((state, prevState) => {
  console.log('[主应用] 全局状态变更:', state, prevState);
});

3.2 子应用获取/更新全局状态 (任意组件.vue)
export default {
  mounted() {
    // 获取通信方法
    const actions = window.__POWERED_BY_QIANKUN__ ? window.__QIANKUN_MAIN_APP__.getGlobalState() : null;

    // 监听主应用状态变更
    actions?.onGlobalStateChange((state) => {
      console.log('[子应用] 收到全局状态:', state);
    });

    // 更新全局状态
    actions?.setGlobalState({ user: { name: 'SubAppUser' } });
  },
};


4. 样式隔离

方案qiankun 的沙箱机制 + CSS 模块化。

4.1 启用 qiankun 样式沙箱
// 主应用启动时开启严格样式隔离
start({ sandbox: { strictStyleIsolation: true } });

4.2 子应用使用 Scoped CSS
<template>
  <div class="subapp-content">子应用内容</div>
</template>

<style scoped>
.subapp-content {
  color: red; /* 样式仅作用于当前组件 */
}
</style>

4.3 避免全局样式污染
  • 子应用避免使用 * 选择器或直接修改 body 样式。
  • 使用 CSS Modules 或 BEM 命名规范。

5. 部署注意事项

  1. 子应用静态资源路径
    vue.config.js 中设置 publicPath 为动态路径:
    module.exports = {
      publicPath: process.env.NODE_ENV === 'production' 
        ? `//your-cdn.com/${name}/` 
        : '/',
    };
    

  2. 跨域支持
    子应用服务器需配置 Access-Control-Allow-Origin: *
  3. 路由冲突
    主应用和子应用避免使用相同的路由路径。

总结

通过以上步骤,可实现:

  • 主应用动态加载子应用
  • 通信机制共享全局状态
  • 样式隔离避免冲突
  • ✅ 子应用独立运行嵌入主应用

完整代码示例可参考 qiankun 官方示例

更多推荐