无星的微前端之旅(四)——qiankun线上服务代理到本地

news/2024/12/13 13:11:24

这个方式其实是我在上家公司的时候体验过,觉得确实很有意思。

所以这里来逆推一下实现方式。

解决了什么痛点

1.开发一个模块,需要启动2-3个项目

在微前端的开发过程中,如果我们要在主应用中看效果,我们至少需要启动一个主应用,和一个待开发模块,如果项目具有登陆机制,我们还需要启动一个登陆模块。

换句话说,为了开发一个模块,我们需要至少启动三个项目。

2.数据耦合的情况下,无法单独启动项目调试

3.特定环境下出现的bug

可能某些bug依赖特定的数据,在测试环境出现了但在本地运行或开发环境运行正常。

如何解决

在成功发布一个版本以后,配置需要在特定条件下触发加载的本地模块,从而将线上服务的某些模块,代理到本地启动的模块,进行开发调试。

如何实现

前面几篇讲到,注册的配置信息其实是可以从远端拉取的,那么只需要有一个配置的地方,我们就可以动态修改这个配置列表。

换句话说,我们可以通过一些代码,配合需要配置列表,进行代理。

1.预设特定条件

比如我们预设一个特定条件:

环境为development或beta环境

成功读取远程配置列表

浏览器localStorage中存在名为developer的值

2.使用可热更新读取的配置表,例如nacos提供

举个例子:
构造一个对象,key表示开发者名字,value为需要代理到本地的数组,item的name为代理模块名称,entry表示入口地址,填写本地的运行地址就行。

// 远程需要读取的配置项
{xingwu:[{name:'sub-login',entry:'//localhost:3002'}]
}

3.修改主应用代码

3.2 main.js

改造前

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
// 注册
import register from './micro/index';
// 添加全局通信
import '@/micro/store';createApp(App).use(store).use(router).mount('#app');
// 注册
register();

改造后

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import api from './api';
// 注册
import register from './micro/index';
// 添加全局通信
import '@/micro/store';createApp(App).use(store).use(router).mount('#app');
// 注册
// 获取远端开发者
const isDevelopment = () => process.env.VUE_APP_ENV_CONFIG === 'development' || process.env.VUE_APP_ENV_CONFIG === 'beta';
if (isDevelopment) {// 网络请求获取远端配置api.getDeveloper().then((response) => {window.subApps = response;}).finally(() => {register();});
} else {register();
}

改造需要的注意点就是注册时机

1.判断环境是否是development环境或beta环境。

这个可以根据配置.env文件中的环境变量属性,在不同环境执行不同mode打包做到。

2.如果加载成功,把加载好的结果存起来。

3.如果加载失败,也得继续注册,不然页面直接挂了。

3.2 subapps

改造前:

import router from '@/router/index';
// 此时在开发,测试环境,理论上已经挂载了subapps的入口
const baseUrl = process.env.BASE_URL;const subapps = [{name: 'sub-login',entry: process.env.VUE_APP_SUB_LOGIN,container: '#sub-apps',activeRule: `${baseUrl}sub-login`,props: {routeBasePath: '/sub-login',mainRouter: router,},},{name: 'sub-user-manage',entry: process.env.VUE_APP_SUB_USER_MANAGE,container: '#sub-apps',activeRule: `${baseUrl}sub-user-manage`,props: {routeBasePath: '/sub-user-manage',mainRouter: router,},},
];export default subapps;

改造后:

import router from '@/router/index';
// 此时在开发,测试环境,理论上已经挂载了subapps的入口
const baseUrl = process.env.BASE_URL;const subapps = [{name: 'sub-login',entry: process.env.VUE_APP_SUB_LOGIN,container: '#sub-apps',activeRule: `${baseUrl}sub-login`,props: {routeBasePath: '/sub-login',mainRouter: router,},},{name: 'sub-user-manage',entry: process.env.VUE_APP_SUB_USER_MANAGE,container: '#sub-apps',activeRule: `${baseUrl}sub-user-manage`,props: {routeBasePath: '/sub-user-manage',mainRouter: router,},},
];// 判断本地是否存在developer
const developer = localStorage.getItem('developer');
if (window.subApps && developer) {// 获取远端定义的入口const tmpArray = window.subApps[developer];if (tmpArray) {tmpArray.forEach((item) => {subapps.forEach((app) => {if (app.name === item.name) {app.entry = item.entry;}});});}
}
export default subapps;

比如上面,我在远端定义了一个开发者xingwu

我只需要再在浏览器的localStorage手动添加一个developer:xingwu

就可以触发匹配,将我指定的模块,加载本地启动的模块,代理到本地。

而其他所有用户所有模块,均不受影响。


就这样,完美解决了上面提出的痛点。

最后给大家看一下效果。



喜欢的朋友记得点赞、收藏、关注哦!!!


https://dhexx.cn/news/show-5466346.html

相关文章

redis cluster 3主3从部署方案

文章目录 1 Redis Cluster 介绍1 Redis cluster 架构2 Redis cluster的工作原理2.1 数据分区2.2 集群通信2.3 集群伸缩2.3.1 集群扩容2.3.2 集群缩容 2.4 故障转移2.4.1 主观下线2.4.2 客观下线 3 Redis Cluster 部署架构说明3.1 部署方式介绍3.2 实战案例:基于Redi…

Envoy 源码解析(一):Envoy 整体架构、Envoy 的初始化

本文基于 Envoy 1.31.0 版本进行源码学习 1、Envoy 整体架构 1)、核心组件 Envoy 包含以下四个核心组件: Listener(监听器):定义了 Envoy 如何处理入站请求。一旦连接建立,请求会被传递给一组过滤器进行处…

golang debug调试

1. 本地调试 1:Add Configurations 添加配置文件(Run kind :Directory) 2:进入run运行窗口 3:debug断点调试模式 1. Resume Program (继续运行) 图标: ▶️ 或 ► 快捷键: F9(Windows/Linux&a…

10个Word自动化办公脚本

在日常工作和学习中,我们常常需要处理Word文档(.docx)。 Python提供了强大的库,如python-docx,使我们能够轻松地进行文档创建、编辑和格式化等操作。本文将分享10个使用Python编写的Word自动化脚本,帮助新…

React进阶面试题目(三)

如何在 React 中实现滚动动画? 在 React 中实现滚动动画可以通过多种方式实现,以下是一个基本的实现步骤: 构建组件:首先构建需要展示滚动动画的组件,例如一个 About 组件,它包含一些文本或元素。监听滚动…

Flutter Container设置padding,margin,背景色,边框

定义:Container是一个组件,当我们需要对基础组件,设置padding,margin,边框,背景色等元素时,就需要通过包裹Container的方式实现。具体如下: 1.magin属性设置: Cont…

在shardingsphere执行存储过程

环境&#xff1a; springboot&#xff1a;2.5.2 数据库&#xff1a;Kingbase金仓V8R6 依赖&#xff1a; <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId></depende…

使用Python编写Windows系统服务管理脚本,主要用于管理mysql、postgresql等服务

提示&#xff1a; 1、理论上该Python脚本可以关闭和开启所有服务 2、搜索服务采用的是模糊搜索 3、常用服务查询: 暂时只写了 mysql、postgresql 如需要其他的自行添加即可 使用方式&#xff08;使用管理员权限运行&#xff09;&#xff1a; 运行方式一&#xff1a;使用管理员…

【Rust 学习笔记】Rust 基础数据类型介绍(一)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 博客内容主要围绕&#xff1a; 5G/6G协议讲解 高级C语言讲解 Rust语言讲解 文章目录 Rust 基础数据类型介绍&#xff08;一&#xff09;一、固定宽…

RabbitMQ高级特性:TTL、死信队列与延迟队列

RabbitMQ高级特性&#xff1a;TTL、死信队列与延迟队列 RabbitMQ作为一款开源的消息代理软件&#xff0c;广泛应用于分布式系统中&#xff0c;用于实现消息的异步传递和系统的解耦。其强大的高级特性&#xff0c;包括TTL&#xff08;Time-To-Live&#xff09;、死信队列&#…