路线规划

项目介绍

  • 整个 SDK 都是围绕 getRoutesApigetUserInfoApi 这两个接口进行设计的,旨在简化微前端应用的开发

  • getRoutesApi 接口用于获取应用路由信息,包括主应用和微应用的路由配置。因为 Qiankunentry 配置比较特殊,在本地开发时是本地服务 "entry": "http://localhost:5174",在生产环境是文件路径 "entry": "/subapp/",所以 主应用 需要使用 vite-plugin-mock 插件 mock 接口

  • getUserInfoApi 接口用于获取用户 user、权限 permissions、角色 role、配置信息 setting,以便进行权限控制和个性化设置。理论上来说 permissions 中应当包含 getRoutesApi 中的所有的路由路径,否则页面出走 <NotPermission /> 组件。(目前的方案是所有的组件手动包一层 <NotPermission />,不在 SDK 中处理权限控制)

  • 微应用使用 sdk.ui.renderComponent('xxx') 时,会报 React 多实例 的错误,需要使用 vite-plugin-externals 插件将 React 等依赖排除在打包之外,更多详情

  • 微应用启动服务时需要加上 --host 参数,否则可能会出现微应用静态资源访问不到的情况。完整命令 "dev": "vite --host"

  • SDK 不能在 组件外 进行使用,否则会报 SDK 未初始化 错误

具体使用

主应用

  • 安装依赖

    1
    2
    3
    4
    5
    // 必须的依赖
    npm install react react-dom react-router-dom@6.30.2 zustand @zxiaosi/sdk

    // 可选的依赖
    npm install antd dayjs
  • main.ts 中进行 SDK 的挂载

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    import {
    sdk,
    SdkApiPlugin,
    SdkAppPlugin,
    SdkClientPlugin,
    SdkConfigPlugin,
    SdkI18nPlugin,
    SdkStoragePlugin,
    SdkStorePlugin,
    SdkUIPlugin,
    } from '@zxiaosi/sdk';
    import { createRoot } from 'react-dom/client';
    import App from './App';

    /** 挂载 SDK */
    sdk
    .use(SdkApiPlugin, {
    getRoutesApi: async () => ({
    code: 0,
    data: [
    { path: '/home', name: '首页', component: 'Home' },
    { path: '/subapp', name: '微应用', component: 'Microapp',
    routeAttr: `{"name": "subapp", "entry": "http://localhost:5174", "activeRule": "/subapp", "rootId": "sub-app"}`,
    },
    ],
    }),
    getUserInfoApi: async () => ({
    code: 0,
    data: { user: {}, permissions: ['/home', '/subapp'], roles: [], settings: {} },
    }),
    loginApi: async () => ({ code: 0, data: { token: 'xxxx' } }),
    })
    .use(SdkAppPlugin)
    .use(SdkClientPlugin)
    .use(SdkConfigPlugin, {
    qiankunMode: 'router',
    proLayoutConfig: {
    title: 'Demo',
    layout: 'mix',
    },
    })
    .use(SdkI18nPlugin)
    .use(SdkStoragePlugin)
    .use(SdkStorePlugin)
    .use(SdkUIPlugin, { Home: () => <div>Home</div> })
    .mount('sdk');

    /** 渲染主应用 */
    createRoot(document.getElementById('root')!).render(<App />);
  • App.tsx 中使用 <Mainapp /> 组件渲染主应用

    1
    2
    3
    4
    5
    6
    7
    8
    import { sdk } from '@zxiaosi/sdk';

    function App() {
    const Mainapp = sdk.ui.getComponent('Mainapp');
    return <Mainapp />;
    }

    export default App;

微应用

  • 安装依赖

    1
    2
    3
    4
    5
    6
    // 必须的依赖
    npm install react react-dom react-router-dom@6.30.2 zustand @zxiaosi/sdk
    npm install vite-plugin-qiankun-lite --save-dev

    // 可选的依赖
    npm install antd dayjs
  • vite.config.ts 中配置 vite-plugin-qiankun-lite 插件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import { defineConfig } from 'vite';
    import react from '@vitejs/plugin-react';
    import qiankun from 'vite-plugin-qiankun-lite';

    export default defineConfig({
    plugins: [
    react(),
    qiankun({ name: 'subapp', sandbox: !!process.env.VITE_SANDBOX }),
    ],
    server: {
    port: 5174,
    },
    });
  • main.ts 中进行 SDK 的继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    import { sdk } from '@zxiaosi/sdk';
    import { createRoot, type Root } from 'react-dom/client';
    import App from './App.tsx';
    import './index.css';

    let root: Root;
    const render = (props: any = {}) => {
    const container = props?.container
    ? props.container.querySelector('#root')
    : document.getElementById('root');

    root = createRoot(container);

    root.render(<App />);
    };

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

    export async function bootstrap() {
    console.log(`Microapp bootstrap`);
    }

    export async function mount(props: any) {
    console.log(`Microapp mount`, props);
    sdk.extend('sdk'); // 继承 sdk 功能
    render(props);
    }

    export async function unmount(props: any) {
    console.log(`Microapp unmount`, props);
    root.unmount();
    }

    export async function update(props: any) {
    console.log(`Microapp update`, props);
    }
  • 可参考项目

相关技术

仓库地址