Qiankun 微前端(React+Vue)基础速通webpack

Qiankun 微前端(React+Vue)基础速通

Qiankun 是基于 single-spa 的微前端框架,核心是主应用注册、子应用独立接入,技术栈无关,适合 React/Vue 混部或独立部署的业务拆分。以下是极简落地流程,覆盖主应用、React/Vue 子应用配置与通信。


📦 核心概念与前置准备

  • 核心术语
    • 主应用(Master):承载所有子应用的"容器",不限技术栈。
    • 子应用(Micro App):独立开发/部署的 React/Vue 应用,需暴露生命周期。
    • 生命周期:bootstrap(初始化)、mount(挂载)、unmount(卸载)。
  • 前置要求:Node.js 16+、React/Vue 基础、Webpack/Vite 配置基础。

🚀 快速上手(主应用 + React/Vue 子应用)

1. 主应用(以 React 为例)

步骤 1:安装依赖

bash 复制代码
npm install qiankun --save
# 或 yarn add qiankun

步骤 2:配置子应用与启动

在主应用入口文件(src/main.jsx)注册子应用,指定路由匹配、挂载容器和入口地址:

jsx 复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import { registerMicroApps, start } from 'qiankun';
import App from './App';

// 注册子应用:React子应用 + Vue子应用
registerMicroApps([
  {
    name: 'react-subapp', // 子应用唯一名称
    entry: '//localhost:3001', // React子应用本地地址
    container: '#subapp-container', // 挂载DOM节点
    activeRule: '/react', // 路由匹配规则(访问/react加载该子应用)
    props: { user: 'admin' }, // 向子应用传参
  },
  {
    name: 'vue-subapp',
    entry: '//localhost:8080', // Vue子应用本地地址
    container: '#subapp-container',
    activeRule: '/vue',
    props: { role: 'user' },
  },
]);

// 启动qiankun(开启预加载与沙箱)
start({
  prefetch: true, // 预加载提升性能
  sandbox: { strictStyleIsolation: true }, // 样式隔离避免冲突
});

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

步骤 3:添加挂载容器

在主应用的 App.jsx 中预留子应用挂载节点:

jsx 复制代码
import { Link } from 'react-router-dom';

function App() {
  return (
    <div>
      <nav>
        <Link to="/">主应用首页</Link>
        <Link to="/react">React子应用</Link>
        <Link to="/vue">Vue子应用</Link>
      </nav>
      {/* 子应用挂载容器 */}
      <div id="subapp-container" style={{ minHeight: '500px' }}></div>
    </div>
  );
}

export default App;
2. React 子应用配置

步骤 1:添加 public-path 配置

src 目录新建 public-path.js,解决子应用资源路径问题:

js 复制代码
// 关键:动态设置publicPath,兼容主应用加载
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

步骤 2:修改入口文件(src/index.js)

导出 Qiankun 生命周期,支持独立运行与主应用加载:

jsx 复制代码
import './public-path'; // 必须在顶部引入
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

// 渲染函数:支持主应用传入的container
function render(props = {}) {
  const { container } = props;
  const rootElement = container ? container.querySelector('#root') : document.getElementById('root');
  const root = ReactDOM.createRoot(rootElement);
  root.render(
    <BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react' : '/'}>
      <App user={props?.user} />
    </BrowserRouter>
  );
}

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

// 暴露Qiankun生命周期
export async function bootstrap() {
  console.log('React子应用初始化');
}
export async function mount(props) {
  console.log('接收主应用参数:', props);
  render(props);
}
export async function unmount(props) {
  const rootElement = props.container ? props.container.querySelector('#root') : document.getElementById('root');
  ReactDOM.unmountComponentAtNode(rootElement);
}

步骤 3:修改 Webpack 配置(支持 CORS)

  • 若用 create-react-app,安装 react-app-rewired 覆盖配置;
  • 若用 Vite,添加 vite-plugin-qiankun 插件。
    示例(react-app-rewired)
    安装依赖:
bash 复制代码
npm install react-app-rewired customize-cra --save-dev

新建 config-overrides.js

js 复制代码
module.exports = {
  webpack: (config) => {
    // 输出库格式,支持主应用加载
    config.output.library = 'react-subapp';
    config.output.libraryTarget = 'umd';
    return config;
  },
  devServer: (configFunction) => {
    return (proxy, allowedHost) => {
      const config = configFunction(proxy, allowedHost);
      // 允许跨域,主应用可访问
      config.headers = { 'Access-Control-Allow-Origin': '*' };
      config.port = 3001; // 与主应用entry端口一致
      return config;
    };
  },
};

修改 package.json 的 scripts:

json 复制代码
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build"
}
3. Vue 子应用配置(Vue3 + Vite 示例)

步骤 1:安装插件

bash 复制代码
npm install vite-plugin-qiankun --save-dev

步骤 2:修改 vite.config.js

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

// 子应用名称,与主应用注册一致
const useDevMode = process.env.NODE_ENV === 'development';

export default defineConfig({
  plugins: [
    vue(),
    qiankun('vue-subapp', {
      useDevMode, // 开发模式下使用独立路由
    }),
  ],
  server: {
    port: 8080, // 与主应用entry端口一致
    cors: true, // 允许跨域
  },
  build: {
    lib: {
      name: 'vue-subapp',
      formats: ['umd'], // 输出umd格式,支持主应用加载
    },
  },
});

步骤 3:修改入口文件(src/main.js)

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

let app = null;

// 渲染函数
function render(props = {}) {
  const { container } = props;
  app = createApp(App);
  app.use(router);
  // 主应用传入的props可通过app.provide传递
  app.mount(container ? container.querySelector('#app') : '#app');
}

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

// 暴露Qiankun生命周期
export async function bootstrap() {
  console.log('Vue子应用初始化');
}
export async function mount(props) {
  console.log('接收主应用参数:', props);
  render(props);
}
export async function unmount() {
  app.unmount();
  app = null;
}

步骤 4:配置路由(src/router/index.js)

js 复制代码
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: () => import('./views/About.vue') },
];

const router = createRouter({
  history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vue' : '/'),
  routes,
});

export default router;

📡 应用间通信

Qiankun 提供两种通信方式,满足不同场景需求:

1. props 传参(简单场景)

主应用注册时通过 props 传参,子应用在 mount 生命周期接收:

jsx 复制代码
// 主应用注册子应用时添加props
registerMicroApps([
  {
    name: 'react-subapp',
    entry: '//localhost:3001',
    container: '#subapp-container',
    activeRule: '/react',
    props: { token: 'xxx-123', userInfo: { name: '张三' } }, // 传参
  },
]);

// React子应用mount中接收
export async function mount(props) {
  console.log('token:', props.token);
  console.log('userInfo:', props.userInfo);
  // 可存储到React Context/Redux
}
2. 全局状态通信(复杂场景)

使用 Qiankun 内置的 onGlobalStateChangesetGlobalState 实现全局状态共享:

jsx 复制代码
// React子应用中监听全局状态变化
export async function mount(props) {
  // 监听全局状态变更
  props.onGlobalStateChange((state, prev) => {
    console.log('全局状态变化:', state, prev);
    // 更新本地状态
    if (state.token) {
      setToken(state.token);
    }
  }, true); // 立即执行一次

  // 修改全局状态
  props.setGlobalState({ count: 1 });
}

⚠️ 常见问题与解决

问题现象 原因 解决方法
子应用资源 404 publicPath 配置错误 子应用必须添加 public-path.js 并在入口顶部引入
样式冲突 主/子应用样式污染 启动时开启 strictStyleIsolation: true,或子应用使用 scoped 样式
跨域报错 子应用未配置 CORS 子应用 devServer 中设置 headers: { 'Access-Control-Allow-Origin': '*' }
路由跳转 404 子应用路由 basename 未设置 React 子应用设置 basename,Vue 子应用通过 vite-plugin-qiankun 自动处理

📚 进阶学习资源


📌 总结

Qiankun 实现 React+Vue 混部的核心是主应用注册、子应用暴露生命周期、解决路径/跨域/样式隔离。按上述步骤完成配置后,即可实现子应用独立开发、独立部署,主应用统一调度。

相关推荐
史迪仔01122 小时前
[QML] Popup 与 Dialog
开发语言·前端·javascript·c++·qt
虹科网络安全2 小时前
艾体宝洞察|NPM供应链攻击:复杂的多链加密货币攻擊渗透流行软件包
前端·npm·node.js
nujnewnehc7 小时前
ps, ai, ae插件都可以用html和js开发了
前端·javascript
Jagger_10 小时前
整洁架构三连问:是什么,怎么做,为什么要用
前端
一个处女座的程序猿O(∩_∩)O11 小时前
React 完全入门指南:从基础概念到组件协作
前端·react.js·前端框架
前端摸鱼匠11 小时前
Vue 3 的defineEmits编译器宏:详解<script setup>中defineEmits的使用
前端·javascript·vue.js·前端框架·ecmascript
里欧跑得慢11 小时前
Flutter 测试全攻略:从单元测试到集成测试的完整实践
前端·css·flutter·web