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

相关推荐
To_OC1 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic1 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy1 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志2 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble3 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯4 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜4 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司5 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
江华森5 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http
IT_陈寒6 小时前
Redis的KEYS命令把我搞崩溃了,改用SCAN才活过来
前端·人工智能·后端