qinakun 微前端

75 阅读2分钟

简介

qiankun 是一个基于微前端的 JavaScript 框架,它允许将多个微应用组合在一起,以创建一个灵活且可扩展的前端架构。该框架由 single-spa 作为基础,但提供了更方便的 API 和配置方式,以使得微前端应用的开发和部署更加简化。

安装依赖

要使用 qiankun,首先你需要将其添加到您的项目中。可以通过 npm 或 yarn 来安装:

bash
# 使用 npm
npm install qiankun

# 使用 yarn
yarn add qiankun

示例配置

1. 设置主应用(基座)

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:3001',
    container: '#yourContainer',
    activeRule: '/app1',
  },
  {
    name: 'app2',
    entry: '//localhost:3002',
    container: '#yourContainer',
    activeRule: '/app2',
  },
]);

start();

2. 设置子应用

// app.js
const { register } = require("qiankun");

const app = {
  mount(props) {
    const { container } = props;
    // 在指定的 container 内部渲染
    ReactDOM.render(<App />, container);
  },

  unmount() {
    // 卸载 React 组件
    ReactDOM.unmountComponentAtNode(container);
  },

  bootstrap() {
    // 初始化代码
  }
};

register({ name: 'app1', app });

React项目示例

主应用项目

import { message } from 'antd';
import { loadMicroApp, MicroApp, registerMicroApps, start } from 'qiankun';
import { useEffect, useRef, FC, useCallback, useState } from 'react';
import { connect, useSelector, useDispatch, history } from 'umi';

interface IProps {}
const ParentApp: FC<IProps> = ({
// props
}) => {
    useEffect(() => {
        if (!microAppRef.current) {
            microAppRef.current = loadMicroApp(
                {
                    // 子应用名称,与入口文件注册时一致
                    name: 'childrenProject',
                    // 子应用项目地址,可直接使用项目链接,也可使用cdn链接
                    entry: '//localhost:3000', // 本地项目链接
                   // entry: '//dev.g.alicdn.com/0.0.1/index.html',cdn链接
                    // 子应用放置容器
                    container: '#childrenProject,
                    props: {
                    //需要传给子应用的属性
                        onCallback
                    },
                },
                {
                    excludeAssetFilter: (url) => {
                        return false;
                    },
                },
            );
        }
        return () => {
            microAppRef.current?.unmount();
        };
    }, []);

    return <div id="childrenProject" />;
};
export default ParentApp;

子应用项目

// src/index.tsx
const { register } = require("qiankun");
import "./public-path.js";
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App.tsx";

let root: any = null;
function render(props) {
  const { container, onCallback } = props;
  root = root ||
    ReactDOM.createRoot(
      container
        ? container.querySelector("#childrenProject_subroot")
        : document.getElementById("childrenProject_subroot")
    );
  root.render(
    <React.StrictMode>
      <App
        onCallback={onCallback}
      />
    </React.StrictMode>
  );
}

if (!window.__POWERED_BY_QIANKUN__) {
  render({});
}

export async function bootstrap() {
  console.log("[react18] react app bootstraped");
}

export async function mount(props) {
  console.log("[react18] props from main framework", props);
  render(props);
}
export async function unmount(props) {
  root.unmount();
  root = null;
}

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    <link rel="manifest" href="./manifest.json" />
   
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="childrenProject_subroot"></div>
  </body>
</html>

src/public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  if (process.env.NODE_ENV === "development") {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
  } else {
    __webpack_public_path__ = "./";
  }
  console.log(
    "microApp publicPath",
    window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
  );
}

public/manifest.json

{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}

注意事项

  • 兼容性:确保微应用使用的框架和库版本互相兼容,尤其是 React/Vue 和构建工具(如 Webpack)之间的版本兼容。
  • CSS隔离:若涉及到样式,考虑使用 CSS Modules 或 CSS-in-JS 解决方案以避免样式冲突。
  • 路径配置:确保在部署的子应用中设置正确的入口(entry)和资源路径,以便主应用能够正确加载它们。

总结

通过 qiankun,可以实现不同微应用的管理和组合,能够显著提高前端项目的灵活性和可维护性。确保在使用的过程中关注各依赖的版本和兼容性,以保证项目的稳定与正常运行。