qiankun基础使用手册

一、创建主应用

创建一个空项目,或者指定一个项目为主应用,下载qiankun

 yarn add qiankun # 或者 npm i qiankun -S

qiankun官网

二、注册子应用

1.在src/qiankun文件夹中创建index.js文件【以主应用为vite+vue为例】
2.在main.js中引入( import ‘./qiankun’ )

import {registerMicroApps, start} from 'qiankun'

// const getActiveRule = (hash) => (location) => location.hash.startsWith(hash)
registerMicroApps([
    {
        // 必须与子应用注册名字相同
        name: 'micro-vue',
        // 入口路径,开发时为子应用所启本地服务,上线时为子应用线上路径
        entry: import.meta.env.MODE === 'development' ? '//localhost:7100' : '/micro-vue/',
        // 子应用挂载的节点
        container: '#subapp-viewport',
        // 当访问路由为 /micro-vue 时加载子应用
        activeRule: '/micro-vue',
        // 主应用向子应用传递参数
        props: {
            mainMsg: '我是来自主应用的值vue'
        }
    },
    {
        name: 'micro-react',
        // entry: '//localhost:7101',
        entry: import.meta.env.MODE === 'development' ? '//localhost:7101' : '/micro-react/',
        container: '#subapp-viewport',
        activeRule: '/micro-react',
        props: {
            msg: '我是来自主应用的值-react'
        }
    }
])
start({
    sandbox: {
        strictStyleIsolation: true
    },
    // 预加载配置
    prefetch: true
})

三、整理主应用路由出口

1.#subapp-viewport(容器名称)才会加载注册的子应用
2.isMicroApp 是否为真,来判断是否是主应用路由
3.通用匹配子应用路由,例如 /micro-vue/:pathMatch(.)
4.至此主应用工作准备完成

1.以App.vue为例
<template>
    <div id="app">
        <div class="header">       
            <router-link to="/">主页</router-link>
            <router-link to="/micro-react">React 应用</router-link>
            <router-link to="/micro-vue">Vue 应用</router-link>
        </div>
        <div class="main-content">
            <!-- 主应用自身路由出口 -->
            <router-view v-if="!$route.meta.isMicroApp" />
            <!-- 子应用挂载容器 -->
            <div id="subapp-viewport" v-else></div>
      
        </div>
    </div>
</template>
2.router/index.js
import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Layout from '../views/layout/index.vue'
import MicroAppContainer from '@/components/MicroAppContainer.vue' // 空壳,区分主应用还是微应用
const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'layout',
            redirect: '/home',
            component: Layout,
            meta: {
                isMicroApp: false
            },
            children: [
                {
                    path: 'home',
                    name: 'home',
                    component: HomeView,
                    meta: {
                        isMicroApp: false
                    }
                },
                {
                    path: 'about',
                    name: 'about',
                    component: () => import('../views/AboutView.vue'),
                    meta: {
                        isMicroApp: false
                    }
                }
            ]
        },
        {
            path: '/micro-vue/:pathMatch(.*)*',
            name: 'micro-vue',
            component: MicroAppContainer,
            meta: {
                isMicroApp: true
            },
            
        },
        {
            path: '/micro-react/:pathMatch(.*)*',
            name: 'micro-react',
            component: MicroAppContainer,
            meta: {
                isMicroApp: true
            }
        }
    ]
})

export default router

四.子应用1 micro-vue (以vite+vue项目为例)

1.检查package.json文件中的name,是不是micro-vue
2.npm i vite-plugin-qiankun 插件
3.更改main.js,区分是作为qiankun子应用还是自主启动访问
4.更改vite.config.js中配置,针对 origin、port、base、plugins的更改
5.子应用1的配置完成,主应用通过/micro-vue访问子应用

1.main.js中代码样例参考
import {createApp} from 'vue'
import {createPinia} from 'pinia'
import App from './App.vue'
import router from './router'
import {qiankunWindow, renderWithQiankun} from 'vite-plugin-qiankun/dist/helper'
import {useUserStore} from '@/stores/user'

let app: any
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
    createApp(App).use(createPinia()).use(router).mount('#app')
} else {
    renderWithQiankun({
        mount(props) {
            app = createApp(App)
            app.use(createPinia())
            app.use(router)
            //在挂载前调用pinia 中的函数,进行zhu应用跟子应用的传值
            const {changeMsg} = useUserStore()

            changeMsg(props.mainMsg)
            app.mount(props.container.querySelector('#app'))

            console.log('子应用挂在了', qiankunWindow.__POWERED_BY_QIANKUN__)
        },
        bootstrap() {
            console.log('[子应用] vue app bootstraped')
        },
        unmount(props: any) {
            if (app) {
                app.unmount()
            }
        }
    })
}

2.vite.config.js中的配置参考
import {fileURLToPath, URL} from 'node:url'
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun'

export default defineConfig(({mode}) => ({
    base: mode === 'development' ? '/micro-vue' : '/micro-vue',
    plugins: [
        vue(),
        qiankun('/micro-vue', {
            // 子应用名字,与主应用注册的子应用名字保持一致
            useDevMode: true
        })
    ],
    resolve: {
        alias: {
            '@': fileURLToPath(new URL('./src', import.meta.url))
        }
    },
    server: {
        host: '0.0.0.0', // 主机地址
        port: 7100, // 端口
        origin: 'http://localhost:7100',
        open: false, // 是否自动打开浏览器
        hmr: true, // 启用热更新
        proxy: {}
    },
    build: {
        outDir: 'micro-vue' //想要把dist修改成什么名字在这边改

    }
}))

五.子应用2 micro-react (以webpack+react项目为例)

1.检查package.json文件中的name,是不是micro-react
2.参考官网给的webpack5的配置
3.创建public-path.js(内容如下)在index.js中引入
4.更改index.js,区分是作为qiankun子应用还是自主启动访问,这里注意下window的挂载是不是在子应用挂载前就存在了
5.更改craco.config.js中配置
6.路由加了basename
7.子应用2的配置完成,主应用通过/micro-react访问子应用

1.public-path.js参考
if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line no-undef
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
2.index.js

import React from "react"
import ReactDOM from "react-dom/client"
import "./index.scss"
import reportWebVitals from "./reportWebVitals"
import { BrowserRouter, RouterProvider } from "react-router-dom"
import router from "./router"
import { Provider } from "react-redux"
import { store } from "./store"
import "./public-path.js"

let root
function render(props) {
    const { container } = props
    const dom = container
        ? container.querySelector("#root")
        : document.getElementById("root")
    root = ReactDOM.createRoot(dom)
    root.render(
        <Provider store={store}>
            <RouterProvider router={router}></RouterProvider>
        </Provider>
    )
}
// 是否是qiankun 环境下
if (!window.__POWERED_BY_QIANKUN__) {
    render({})
}

export async function bootstrap() {
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {

    render(props)
}

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

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
    console.log("update props", props)
}
window.qiankunLifecycle = {
    bootstrap,
    mount,
    unmount,
    update,
}
reportWebVitals()
3.craco.config.js配置参考
const path = require("path")
const packageName = require("./package.json").name
const isDevelopment = process.env.NODE_ENV === "development"

module.exports = {
    // webpack配置
    webpack: {
        output: {
            library: `${packageName}-[name]`,
            libraryTarget: "umd",
            chunkLoadingGlobal: `webpackJsonp_${packageName}`,
            globalObject: "window",
            filename: "[name].bundle.js",
            clean: true,
            publicPath: isDevelopment ? "//localhost:7101/" : "/micro-react/",
        },

        // 配置别名
        alias: {
            // 约定制定
            "@": path.resolve(__dirname, "src"),
        },
    },
    devServer: {
        host: "0.0.0.0", // 主机地址
        port: 7101, // 端口
        open: false, // 是否自动打开浏览器
        hot: true, // 启用热更新
        proxy: {       
        },   
    },
}
4.router/index.js
import React, { lazy } from "react"
import { createBrowserRouter } from "react-router-dom"
import Layout from "@/pages/layout"
import Login from "@/pages/login"
import Home from "../pages/home"

// 区分环境
const basename = window.__POWERED_BY_QIANKUN__ ? "/micro-react" : "/"

const router = createBrowserRouter(
    [
        {
            path: "/",
            element:<Layout />  ,
            children: [
                {
                    path: "home",                   
                    element: <Home />,
                },
            ],
        },
        {
            path: "/login",
            element: <Login />,
        },
    ],
    {
        basename: basename,
    }
)

export default router

六、路由跳转并传参

1.router 提供的跳转方法,只支持在本应用中跳转,但不支持跨应用
2.以react跳转vue应用并传参为例
3.在react中添加按钮并添加点击事件
4.在vue项目中接收

1.react中传递
  const goVue = () => {
        window.history.pushState({ reactMsg: "你好vue" }, "", "/micro-vue")
    }
2.vue项目中接收
onMounted(() => {
    console.log('vue页面挂载了', window.history)
    msg.value = window.history.state.reactMsg
})

七、通过stores管理多个应用的状态

1.通过主应用的store,给子应用传递一个函数,子应用在mount接收并保存,在合适的页面调用,触发,通过主应用分发到其他子应用(场景不是很多见)

八、使用Ant Design、Element组件库出现弹框样式问题配置

1.在主应用中这样设置规则

sandbox: {
        strictStyleIsolation: false, //  基于浏览器原生功能 Shadow DOM[它允许将一个隐藏的、独立的 DOM 树附加到常规的 DOM 节点中]
        experimentalStyleIsolation: true // 利用 PostCSS 插件,在子应用的样式规则上添加一个 限定选择器
    }

2.ant-design中提供了ConfigProvider

<ConfigProvider
    getPopupContainer={getPopupContainer}
    calendar={() => getPopupContainer}
>
    <RouterProvider router={router}></RouterProvider>
</ConfigProvider>

3.针对element plus 我没有做什么更改
4.后续在补充下element的

qiankun搭建遇到的问题总结

1.组件库中弹框样式问题

Error with push/replace State SecurityError: Failed to execute ‘replaceState’ on ‘History’: A history state object with URL ‘http://localhost:5173undefined/’ cannot be created in a document with origin

点击完ant-design弹框,再次切换其他应用时
我在主应用中路由跳转的时候使用了push,保留浏览历史,但是我上个容器已经消失了,没有重新创建,改用replace跳转解决这个问题

2.路由版本问题

1.提供base或者basename的时候,注意路由版本,以及提供的位置

3.挂载容器不存在排查问题

1.路由是不是匹配
2.是不是处在qiankun环境下等

4.如果是webpack构建的项目,参考qiankun官网使用手册

5.具体应用持续更新…

参考链接

使用微前端(qiankun),解决样式污染问题
wujie和qiankun对比
遇到的问题总结

### Qiankun前端框架与Vite构建工具的集成 #### 安装必要的依赖包 为了使项目能够支持Qiankun并利用Vite的优势,在主应用中需安装`vue-router`和`qiankun`作为主要依赖项;而在子应用方面,则应引入`vite-plugin-qiankun-lite`来简化配置流程[^4]。 对于主应用而言,执行以下命令以添加所需软件包: ```bash pnpm install vue-router qiankun ``` 针对子应用来说,通过下面这条指令可以获取到轻量级版本的插件,并将其标记为开发阶段使用的依赖: ```bash pnpm install vite-plugin-qiankun-lite -D ``` #### 创建基础结构 创建两个简单的HTML文件代表不同的页面视图。这一步骤有助于理解如何在实际场景下组织各个组件之间的关系以及它们是如何被加载进来的。 #### 修改Vite配置文件 为了让Vite更好地配合Qiankun工作,需要调整项目的`vite.config.ts`文件。具体做法是在其中加入来自`vite-plugin-qiankun`的相关设置选项,从而确保整个系统的正常运作[^1]。 以下是修改后的样例代码片段: ```typescript import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import qiankun from 'vite-plugin-qiankun' export default defineConfig({ plugins: [ vue(), qiankun('appName', { // 这里放置特定于当前应用实例化的参数... }) ] }) ``` 上述配置使得Vite能够在编译过程中识别由Qiankun管理的应用程序名称及其初始化所需的其他信息。 #### 实现跨域资源共享(CORS) 考虑到不同源之间可能存在资源访问权限的问题,建议提前处理好CORS策略。可以通过适当的方式允许目标域名下的请求到达服务器端口,进而促进各服务间的顺畅交互[^2]。 #### 测试环境搭建 完成以上准备工作之后,就可以启动本地的服务来进行初步验证了。此时应该能看到预期的效果——即多个独立的小型Web应用程序可以在同一个浏览器窗口中共存而不发生冲突[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值