qiankun微前端:qiankun+vite+vue3+ts(未完待续..)
目录
什么是微前端
目前现有的微前端
好处
使用
子应用的页面
在主应用里显示 
什么是微前端
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。
我的理解就是将一个大型的前端应用拆分成多个模块,每个微前端模块可以由不同的团队进行管理,并可以自主选择框架,并且有自己的仓库,可以独立部署上线。
目前现有的微前端方案
iframe
通过iframe实现的话就是每个子应用通过iframe标签来嵌入到父应用中,iframe具有天然的隔离属性,各个子应用之间以及子应用和父应用之间都可以做到互不影响。
但是iframe也有很多缺点:
- url不同步,如果刷新页面,iframe中的页面的路由会丢失。
- 全局上下文完全隔离,内存变量不共享。
- UI不同步,比如iframe中的页面如果有带遮罩层的弹窗组件,则遮罩就不能覆盖整个浏览器,只能在iframe中生效。
- 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程
single-spa
single-spa是最早的微前端框架,可以兼容很多技术栈。
single-spa首先在基座中注册所有子应用的路由,当URL改变时就会去进行匹配,匹配到哪个子应用就会去加载对应的那个子应用。
相对于iframe的实现方案,single-spa中基座和各个子应用之间共享着一个全局上下文,并且不存在URL不同步和UI不同步的情况,但是single-spa也有以下的缺点:
- 没有实现js隔离和css隔离
- 需要修改大量的配置,包括基座和子应用的,不能开箱即用
qiankun
基于single-spa二次开发,封装了开箱即用的api
资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
实现了样式隔离
基于qiankun的微前端实战
准备两个空项目
- qiankun-base 主应用
- qiankun-child vue 子应用
创建基座项目qiankun-base和qiankun-child-vue
创建一个vue3+vite+tsx项目详情见 创建一个vue3+vite+ts项目
vue子应用 qiankun-child-vue
修改.env
VITE_APP_NAME = qiankun-child-vue
修改根节点挂载id
index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/vite.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>qiankun-child-vue</title></head><body><div id="qiankun-child-vue"></div><script type="module" src="/src/main.ts"></script></body>
</html>main.tsimport { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router";
import antv from "ant-design-vue";
const app = createApp(App);
app.use(router).use(antv).mount("#qiankun-child-vue");
配置子应用菜单
/views/index.tsx
import { defineComponent, h, reactive, ref } from "vue";
import { Menu, SubMenu, MenuItem, ItemType } from "ant-design-vue";
import "./index.css";
import { RouterView, useRouter } from "vue-router";
// 展平数组
const flattenMenu = (list) => {const res: any = [];if (!list) return;list.forEach((item) => {res.push(item);if (item.children) res.push(...flattenMenu(item.children));});return res;
};
const getMenuKey = (menuList, key) => {const allList = flattenMenu(JSON.parse(JSON.stringify(menuList)));const cur = allList.find((item) => item.key == key);return cur ? cur : {};
};export default defineComponent({setup() {const router = useRouter();const menuList = ref([{key: "1",label: "子应用菜单",url: "/qiankun-child-vue",children: [{ label: "设置", key: "2", url: "/qiankun-child-vue/setting" },],},]);// 找到点击的菜单对象const handleMenuSelect = (params) => {const menu = getMenuKey(menuList.value, params.key);router.push(menu.url);};return () => (<a-layout class="layout"><a-layout-sider><MenuonSelect={handleMenuSelect}style="height:100%"mode="inline"items={menuList.value}></Menu></a-layout-sider><a-layout-content><RouterView></RouterView></a-layout-content></a-layout>);},
});
新建/views/setting.tsx
import { defineComponent, ref } from "vue";export default defineComponent({setup() {return () => <div>设置</div>;},
});
配置路由 /router/index.ts
import { createRouter, createWebHashHistory } from "vue-router";
import Index from "@/views/index";
const router = createRouter({history: createWebHashHistory(),routes: [{path: "/",component: Index,children: [{path: "/qiankun-child-vue/setting",name: "setting",component: () => import("@/views/setting"),},],},],
});export default router;
基本的页面就搭建好了
基座 qiankun-base
同样在/views/index.tsx 写好基本的菜单
配置路由 /router/index.ts
import { createRouter, createWebHashHistory } from "vue-router";
import Index from "@/views";const router = createRouter({history: createWebHashHistory(),routes: [{path: "/:afterUser(.*)", // 正则匹配url 跳转不会报错component: Index,},],
});export default router;
配置vite.config.js 根路径base
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { resolve } from "path";
export const pathResolve = (dir: string) => resolve(process.cwd(), ".", dir);export default defineConfig(({ mode }) => {return {base: "/qiankun-base/",plugins: [vue(), vueJsx()],server: {host: "0.0.0.0",port: 1000,},resolve: {alias: {"@": pathResolve("src"),},},};
});
修改dom根节点 和主应用一样改为子应用的项目名称 改这个是为了主应用和子应用的挂载在根节点的id不会重复,如果一样的话会导致主应用页面渲染不出来子应用(这里不在展示细节)
qiankun配置步骤(上面还没开始)
主应用qiankun-base中下载qiankun
yarn add qiankun
在main.ts中开启
注意:在挂载之前开启
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import { start } from "qiankun";
import router from "./router";
import antv from "ant-design-vue";
start({sandbox: {// strictStyleIsolation: true, // 开启严格的样式隔离模式experimentalStyleIsolation: true, // 开启后所有样式都会加上一个类名 .app-main {} ===> div[data-qiankun-react16] .app-main {}},singular: false, // 单一时间只渲染一个微应用,默认为true
});
createApp(App).use(router).use(antv).mount("#qiankun-base");
vue子应用 qiankun-child-vue
下载vite-plugin-qiankun插件
yarn add vite-plugin-qiankun
配置vite.config.js 使用vite-plugin-qiankun
import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import qiankun from "vite-plugin-qiankun";
import { resolve } from "path";export const pathResolve = (dir: string) => resolve(process.cwd(), ".", dir);export default defineConfig(({ mode }) => {const env = loadEnv(mode, process.cwd());return {base: mode == "production" ? `/${env.VITE_APP_NAME}/` : "",plugins: [vue(),vueJsx(),qiankun(env.VITE_APP_NAME, { useDevMode: true }),],server: {host: "0.0.0.0",port: 2000,},resolve: {alias: {"@": pathResolve("src"),},},};
});
修改main.ts 判断是在主应用还是子应用中
import "./style.css";
import App from "./App.vue";
import router from "./router";
import antv from "ant-design-vue";
import { render } from "@/hooks/microApp";render(App, "#qiankun-child-vue", (app, props) => {app.use(router).use(antv);
});
/hooks/microApp.ts
import renderWithQiankun, {QiankunProps,qiankunWindow,
} from "vite-plugin-qiankun/dist/helper";
import { App, Component, createApp } from "vue";const isMicroApp = qiankunWindow.__POWERED_BY_QIANKUN__;
export const render = (AppRoot: Component,domId,configApp: (app: App, props?: QiankunProps) => any
) => {let app: App;const _render = (props: QiankunProps = {}) => {const { container } = props;const root: string | Element = container? container.querySelector(domId)!: domId; // 避免 id 重复导致微应用挂载失败app = createApp(AppRoot);// 回调配置app的函数 让调用的地方 可以使用appconfigApp(app, props);app.mount(root);};const initQiankun = () => {renderWithQiankun({bootstrap() {// console.log("微应用:bootstrap");},mount(props) {// 获取主应用传入数据// console.log("微应用:mount", props);_render(props);},unmount(props) {// console.log("微应用:unmount", props);app.unmount();},update(props) {// console.log("微应用:update", props);},});};isMicroApp ? initQiankun() : _render();
};
在views/index.tsx 增加判断逻辑 是在主应用中还是在子应用中
import { qiankunWindow } from "vite-plugin-qiankun/dist/helper";return () => {
// 判断如果在主应用中if (qiankunWindow.__POWERED_BY_QIANKUN__) {return <router-view></router-view>;}
// 在子应用中return (<a-layout class="layout"><a-layout-sider><MenuonSelect={handleMenuSelect}style="height:100%"mode="inline"items={menuList.value}></Menu></a-layout-sider><a-layout-content><RouterView></RouterView></a-layout-content></a-layout>);};
易错点
1.主应用和子应用挂载在根节点的domid是同一个
2.主应用配置路径和子应用路径不一致
相关文章:
qiankun微前端:qiankun+vite+vue3+ts(未完待续..)
目录 什么是微前端 目前现有的微前端 好处 使用 子应用的页面在主应用里显示 什么是微前端 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。 我的理解就是将一个大型的前端应用拆分成多个模块,每个微前端模块可以由…...
001:开源交易系统开发实战开篇
本专栏采用融入【主力思维】的方法学,包含数据抓取、特征模型开发、历史验证回归测试、每日动态风险评估管理等技术,较大的增强股票投资胜率,让IT开发者拥有一套属于自己思路的专用交易软件。 先简要介绍系统成功和项目,后续持续…...
Pytorch实战(一):LeNet神经网络
文章目录 一、模型实现1.1数据集的下载1.2加载数据集1.3模型训练1.4模型预测 LeNet神经网络是第一个卷积神经网络(CNN),首次采用了卷积层、池化层这两个全新的神经网络组件,接收灰度图像,并输出其中包含的手写数字&…...
RabbitMq的基础及springAmqp的使用
RabbitMq 官网:RabbitMQ: One broker to queue them all | RabbitMQ 什么是MQ? mq就是消息队列,消息队列遵循这先入先出原则。一般用来解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用…...
uniapp uniCloud云开发
uniCloud概述 uniCloud 是 DCloud 联合阿里云、腾讯云、支付宝云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。 uniCloud 的 web控制台地址:https://unicloud.dcloud.net.cn 文档:https://doc.dcloud.net.cn/uniCloud/ un…...
智能扫地机,让生活电器更加便民-NV040D扫地机语音方案
一、语音扫地机开发背景: 随着人工智能和物联网技术的飞速发展,智能家居设备已成为现代家庭不可或缺的一部分。其中,扫地机作为家庭清洁的重要工具,更是得到了广泛的关注和应用。 然而,传统的扫地机在功能和使用上仍存…...
【后端面试题】【中间件】【NoSQL】ElasticSearch索引机制和高性能的面试思路
Elasticsearch的索引机制 Elasticsearch使用的是倒排索引,所谓的倒排索引是相对于正排索引而言的。 在一般的文件系统中,索引是文档映射到关键字,而倒排索引则相反,是从关键字映射到文档。 如果没有倒排索引的话,想找…...
【漏洞复现】时空智友ERP updater.uploadStudioFile接口处存在任意文件上传
0x01 产品简介 时空智友ERP是一款基于云计算和大数据技术的企业资源计划管理系统。该系统旨在帮助企业实现数字化转型,提高运营效率、降低成本、增强决策能力和竞争力,时空智友ERP系统涵盖了企业的各个业务领域,包括财务管理、供应链管理、生…...
[leetcode hot 150]第五百三十题,二叉搜索树的最小绝对差
题目: 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数,其数值等于两值之差的绝对值。 解析: minDiffInBST 方法是主要方法。创建一个 ArrayList 来存储树的节点值。inorderTrave…...
【Docker】可视化平台Portainer
文章目录 Portainer的特点Portainer的安装步骤注意事项 Docker的可视化工具Portainer是一个轻量级的容器管理平台,它为用户提供了一个直观的图形界面来管理Docker环境。以下是关于Portainer的详细介绍和安装步骤: Portainer的特点 轻量级:P…...
MySQL高级-MVCC-原理分析(RR级别)
文章目录 1、RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView2、总结 1、RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView 而RR 是可重复读,在一个事务中&…...
压力测试Monkey命令参数和报告分析
目录 常用参数 -p <测试的包名列表> -v 显示日志详细程度 -s 伪随机数生成器的种子值 --throttle < 毫秒> --ignore-crashes 忽略崩溃 --ignore-timeouts 忽略超时 --monitor-native-crashes 监视本地崩溃代码 --ignore-security-exceptions 忽略安全异常 …...
C# Benchmark
创建控制台项目(或修改现有项目的Main方法代码),Nget导入Benchmark0.13.12,创建测试类: public class StringBenchMark{int[] numbers;public StringBenchMark() {numbers Enumerable.Range(1, 20000).ToArray();}[Be…...
算法金 | 协方差、方差、标准差、协方差矩阵
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 抱个拳,送个礼 1. 方差 方差是统计学中用来度量一组数据分散程度的重要指标。它反映了数据点与其均值之间的偏离程度。在…...
FastAPI教程II
本文参考FastAPI教程https://fastapi.tiangolo.com/zh/tutorial Cookie参数 定义Cookie参数与定义Query和Path参数一样。 具体步骤如下: 导入Cookie:from fastapi import Cookie声明Cookie参数,声明Cookie参数的方式与声明Query和Path参数…...
Facebook的投流技巧有哪些?
相信大家都知道Facebook拥有着巨大的用户群体和高转化率,在国外社交推广中的影响不言而喻。但随着Facebook广告的竞争越来越激烈,在Facebook广告上获得高投资回报率也变得越来越困难。IPIDEA代理IP今天就教大家如何在Facebook上投放广告的技巧࿰…...
Spring Boot 中的微服务监控与管理
微服务的概述 微服务架构的优点和挑战 优点: 灵活性和可扩展性:微服务架构允许每个服务单独部署和扩展,这使得系统可以更灵活地适应不同的业务需求和负载变化。 使团队更加聚焦:每个微服务都有明确的职责,这使得开发团队可以更加聚焦,专注于开发他们的服务。 技术和框…...
【计算机网络】期末复习(1)模拟卷
一、选择题 1. 电路交换的三个阶段是建立连接、()和释放连接 A. Hello包探测 B. 通信 C. 二次握手 D. 总线连接 2. 一下哪个协议不属于C/S模式() A. SNMP…...
【软件工程中的演化模型及其优缺点】
文章目录 1. 增量模型什么是增量模型?优点缺点 2. 增量-迭代模型什么是增量-迭代模型?优点缺点 3. 螺旋模型什么是螺旋模型?优点缺点 1. 增量模型 什么是增量模型? 增量模型是一种逐步增加功能和特性的开发方法。项目被划分为多…...
Oracle 数据库详解:概念、结构、使用场景与常用命令
1. 引言 Oracle 数据库作为全球领先的关系型数据库管理系统(RDBMS),在企业级应用中占据了重要地位。本文将详细介绍Oracle数据库的核心概念、架构、常用操作及其广泛的使用场景,旨在为读者提供全面而深入的理解。 2. Oracle 数据…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
