使用qiankun搭建微前端应用及踩坑

线上演示地址:React App

源码地址:https://github.com/Jiang-K-J/micro-app?tab=readme-ov-file (帮忙点个小星星)

主应用:react 18+

子应用:vite + vue3

子应用:react 18+

安装

  1. 主应用

    $ yarn add qiankun # 或者 npm i qiankun -S

  2. 子应用(如果你的子应用不是vite构建的,你无需安装任何插件)

    npm i vite-plugin-qiankun

搭建

在主应用中注册子应用
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react app', // 子应用的名称
    entry: '//localhost:7100', // 子应用运行的url和port
    container: '#yourContainer', // 用于放置子应用显示的载体
    activeRule: '/sub-react', // 匹配的路由
  },
  {
    name: 'vue app',
   entry: '//localhost:3000',
    container: '#yourContainer',
    activeRule: '/sub-vue',
  },
]);

start();
子应用配置
  • vite子应用

    import { createApp } from 'vue'
    import App from './App.vue'
    import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
    import { router, abstractRouter } from './router';
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'

    let app;
    if (!qiankunWindow.POWERED_BY_QIANKUN) {
    createApp(App).use(router).use(ElementPlus).mount('#app');
    } else {
    renderWithQiankun({
    // 子应用挂载
    mount(props) {
    let routerInstance = null;
    console.log('props', props?.path);
    if (props?.path) {
    routerInstance = abstractRouter;
    } else {
    routerInstance = router;
    }
    app = createApp(App);
    // 使用 provide 将 props 传递给所有后代组件
    app.provide('qiankunProps', props);
    app.use(routerInstance).use(ElementPlus);
    app.mount(props.container.querySelector('#app'));
    if (props?.path) {
    routerInstance.push(props.path)
    }
    },
    // 只有子应用第一次加载会触发
    bootstrap() {
    console.log('vue app bootstrap');
    },
    // 更新
    update() {
    console.log('vue app update');
    },
    // 卸载
    unmount() {
    console.log('vue app unmount');
    app?.unmount();
    }
    });
    }

  • react子应用

    import React from "react";
    import { createRoot } from "react-dom/client";
    import { BrowserRouter, MemoryRouter } from "react-router-dom";
    import { QiankunContext } from "./QiankunContext.jsx";
    import "./index.css";
    import App from "./App";
    import "./public-path"; // webpack子应用需要新增一个这样的文件,下方有说明
    import "./a1.js";

    let root;
    function render(props) {
    const { container,path } = props;
    const RouterWrapper = props?.path ? MemoryRouter : BrowserRouter;
    const dom = container
    ? container.querySelector("#root")
    : document.getElementById("root");
    root = createRoot(dom);
    root.render(
    <RouterWrapper basename="/sub-react" initialEntries={path ? [path] : ["/"]}>
    <QiankunContext.Provider value={props}>
    <App mianProps={props} />
    </QiankunContext.Provider>
    </RouterWrapper>
    );
    }

    // 判断是否在qiankun环境下,非qiankun环境下独立运行
    if (!window.POWERED_BY_QIANKUN) {
    render({});
    }

    // 各个生命周期
    // bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
    export async function bootstrap() {
    console.log("react app bootstraped");
    }

    // 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
    export async function mount(props) {
    console.log("props from main framework", props);
    render(props);
    }

    // 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
    export async function unmount(props) {
    root.unmount();
    }

    basename="/sub-react" 这个和你在主应用注册子应用中的activeRule要保持一直

webpack构建的子应用需要新增下面的文件,并在入口文件中进行导入

src 目录新增 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
子应用配置文件修改
  • webpack构建的应用

由于webpack构建的应用一般不会暴露webpack文件,我们这里可以下载 react-app-rewired 这个插件用于修改webpack配置,具体可以百度一下

const { name } = require("./package");

module.exports = {
  webpack: (config) => {
    // 设置输出配置
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = "umd";
    config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;

    return config;
  },
  devServer: (_) => {
    const config = _;

    config.headers = {
      "Access-Control-Allow-Origin": "*",
    };
    config.historyApiFallback = true;
    config.hot = false;
    config.watchContentBase = false;
    config.liveReload = false;

    return config;
  },
};
  • vite构建的应用

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import qiankun from 'vite-plugin-qiankun';
    export default defineConfig({
    base: '/sub-vue', // 和基座中配置的activeRule一致
    server: {
    port: 3000,
    cors: true,
    origin: 'http://localhost:3000' //你的实际运行地址
    },
    plugins: [
    vue(),
    qiankun('sub-vue', { // 配置qiankun插件
    useDevMode: true
    }),
    ]
    })

    这里还需要配置下方那部分内容,具体怎样在vite中配置output,可以百度一下

    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`, // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    },
    

具体配置可以参考官网文档:项目实践 - qiankun

建议:vite应用中base配置应该和实际线上地址保持一致,这样可以避免很多保持:

base: 'http://xxx:3000/sub-vue', // 和基座中配置的activeRule一致

部署

部署主要是nginx配置,没有别的操作

主应用

    location / {
      add_header Cache-Control no-cache;
      index index.html;
      try_files $uri /index.html;
    }

子应用

# /sub-react 这个需要和activeRule保持一致即可
 location /sub-react {
     # 设置允许的跨域来源
        alias /web/qiankun/rf; # 指向静态文件目录
        index index.html;
        try_files $uri /index.html; # 注意这里的路径,仅需指向子应用的 `index.html`
    }
    
    
    location / {
  
      # 添加跨域头
      add_header Access-Control-Allow-Origin *;
      add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
      add_header Access-Control-Allow-Headers "Content-Type, Authorization";
  
      if ($request_method = OPTIONS) {
          add_header Access-Control-Allow-Origin *;
          add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
          add_header Access-Control-Allow-Headers "Content-Type, Authorization";
          return 204;
      }
    }

踩坑汇总

相关推荐
m0_748230941 小时前
Redis 通用命令
前端·redis·bootstrap
YaHuiLiang1 小时前
一切的根本都是前端“娱乐圈化”
前端·javascript·代码规范
ObjectX前端实验室3 小时前
个人网站开发记录-引流公众号 & 谷歌分析 & 谷歌广告 & GTM
前端·程序员·开源
CL_IN3 小时前
企业数据集成:实现高效调拨出库自动化
java·前端·自动化
浪九天4 小时前
Vue 不同大版本与 Node.js 版本匹配的详细参数
前端·vue.js·node.js
qianmoQ4 小时前
第五章:工程化实践 - 第三节 - Tailwind CSS 大型项目最佳实践
前端·css
尚学教辅学习资料5 小时前
基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考
vue.js·spring boot·uni-app·旅游
椰果uu5 小时前
前端八股万文总结——JS+ES6
前端·javascript·es6
微wx笑5 小时前
chrome扩展程序如何实现国际化
前端·chrome
~废弃回忆 �༄5 小时前
CSS中伪类选择器
前端·javascript·css·css中伪类选择器