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 数据…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...