使用 qiankun 微前端框架的心得与实践

什么是 qiankun?

qiankun 是一个基于 single-spa 的微前端实现库,由蚂蚁金服团队开发。它旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。

在我最近的项目中,我有幸使用了 qiankun 来整合多个独立的前端应用,今天就来分享一下我的使用心得和实际案例。

为什么选择微前端?

在介绍 qiankun 的具体使用前,先简单说说为什么我们需要微前端:

  1. 技术栈无关​ - 各个子应用可以使用不同的技术栈(React、Vue、Angular 等)

  2. 独立开发​ - 各个团队可以独立开发、测试、部署自己的应用

  3. 渐进式迁移​ - 可以逐步迁移老系统,而不是一次性重写

  4. 应用自治​ - 每个微应用都是独立的代码库,有自己的发布流程

基础案例:主应用配置

1. 安装 qiankun

复制代码
npm install qiankun
# 或者
yarn add qiankun

2. 主应用入口文件配置

复制代码
// main.js
import { registerMicroApps, start } from 'qiankun';

// 注册微应用
registerMicroApps([
  {
    name: 'react-app', // 微应用名称
    entry: '//localhost:7100', // 微应用入口
    container: '#subapp-container', // 微应用挂载节点
    activeRule: '/react', // 微应用激活规则
  },
  {
    name: 'vue-app',
    entry: '//localhost:7101',
    container: '#subapp-container',
    activeRule: '/vue',
  },
]);

// 启动 qiankun
start({
  sandbox: {
    strictStyleIsolation: true, // 开启样式隔离
  },
});

3. HTML 模板设置

复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>主应用</title>
</head>
<body>
  <div id="root">
    <h1>主应用</h1>
    <ul>
      <li><a href="/react">React 应用</a></li>
      <li><a href="/vue">Vue 应用</a></li>
    </ul>
    <div id="subapp-container"></div>
  </div>
</body>
</html>

微应用配置

React 微应用配置

复制代码
// react-app/src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
  // 动态设置 webpack publicPath,防止资源加载出错
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

// react-app/src/index.js
import './public-path';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

function render(props) {
  const { container } = props;
  ReactDOM.render(
    <App />,
    container ? container.querySelector('#root') : document.querySelector('#root')
  );
}

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

// 生命周期函数必须返回 Promise
export async function bootstrap() {
  console.log('[react16] react app bootstraped');
}

export async function mount(props) {
  console.log('[react16] props from main framework', props);
  render(props);
}

export async function unmount(props) {
  const { container } = props;
  ReactDOM.unmountComponentAtNode(
    container ? container.querySelector('#root') : document.querySelector('#root')
  );
}

Vue 微应用配置

复制代码
// vue-app/src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

// vue-app/src/main.js
import './public-path';
import Vue from 'vue';
import App from './App.vue';

let instance = null;

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

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

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}

export async function mount(props) {
  console.log('[vue] props from main framework', props);
  render(props);
}

export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
}

Webpack 配置修改

复制代码
// vue.config.js 或 webpack.config.js
const packageName = require('./package.json').name;

module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*', // 允许跨域
    },
  },
  configureWebpack: {
    output: {
      library: `${packageName}-[name]`,
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${packageName}`,
    },
  },
};

实际使用中的心得体会

1. 样式隔离问题

qiankun 提供了两种样式隔离方案:

复制代码
start({
  sandbox: {
    strictStyleIsolation: true, // 使用 Shadow DOM 实现严格隔离
    experimentalStyleIsolation: true, // 实验性样式隔离
  }
});

在实际使用中,我发现 strictStyleIsolation虽然隔离效果好,但可能会影响一些 UI 库的样式。而 experimentalStyleIsolation是通过给样式添加前缀实现的,兼容性更好。

2. 应用间通信

qiankun 提供了简单的通信机制:

复制代码
// 主应用初始化
import { initGlobalState } from 'qiankun';

const actions = initGlobalState({
  user: { name: '张三' },
});

// 监听状态变化
actions.onGlobalStateChange((state, prev) => {
  console.log('主应用: 状态变化', state, prev);
});

// 微应用中获取和设置状态
export function mount(props) {
  // 监听状态变化
  props.onGlobalStateChange((state, prev) => {
    console.log('微应用: 状态变化', state, prev);
  });
  
  // 设置全局状态
  props.setGlobalState({ user: { name: '李四' } });
}

3. 路由处理技巧

// 主应用路由配置

registerMicroApps([

{

name: 'app1',

entry: '//localhost:7100',

container: '#subapp-container',

activeRule: '/app1',

props: {

routerBase: '/app1', // 传递路由基础路径

}

},

]);

// 微应用中使用

if (window.POWERED_BY_QIANKUN) {

// 从主应用传递的 props 中获取路由基础路径

const { routerBase } = props;

// 在微应用路由配置中使用

}

遇到的坑与解决方案

1. 静态资源路径问题

微应用中的静态资源路径需要特别注意,解决方案是使用相对路径或动态设置 publicPath。

2. 第三方脚本冲突

有些第三方库会修改全局对象,可能导致冲突。解决方案是在微应用卸载时清理全局状态。

3. 开发环境调试

开发时可以通过设置 window.__POWERED_BY_QIANKUN__ = true来模拟微前端环境进行调试。

总结

经过几个月的实践,我认为 qiankun 是一个相当成熟的微前端解决方案。它解决了微前端架构中的很多复杂问题,让开发者可以更专注于业务逻辑。

优点:

  • 接入简单,学习成本低

  • 功能完善,文档清晰

  • 社区活跃,问题解决及时

需要注意的地方:

  • 样式隔离需要根据实际情况选择合适方案

  • 应用间通信要设计合理,避免过度耦合

  • 部署和运维相对复杂

总的来说,如果你的项目需要整合多个前端应用,或者正在进行前端架构的现代化改造,qiankun 绝对值得一试。希望我的经验对你有帮助!

相关推荐
y***54886 小时前
React依赖
前端·react.js·前端框架
2***B4496 小时前
React测试
前端·react.js·前端框架
5***o5006 小时前
React自动化测试
前端·react.js·前端框架
T***u3336 小时前
React部署
前端·react.js·前端框架
低保和光头哪个先来7 小时前
场景2:Vue Router 中 query 与 params 的区别
前端·javascript·vue.js·前端框架
e***U8201 天前
React Hooks性能优化
前端·react.js·前端框架
4***R2401 天前
React数据分析
前端·react.js·前端框架
X***E4631 天前
React课程
前端·react.js·前端框架
ArkPppp1 天前
大道至简-Shadcn/ui设计系统初体验(下):Theme与色彩系统实战
前端·前端框架