微前端 无界wujie
开发环境配置:
Node.js 版本 < 18.0.0
pnpm 脚手架示例模版基于 pnpm + turborepo 管理项目
如果您的当前环境中需要切换 node.js 版本, 可以使用 nvm or fnm 进行安装.
以下是通过 nvm 或者nvs 安装 Node.js 16 LTS 版本
nvs安装教程 https://blog.csdn.net/glorydx/article/details/134056903
C:\>node -v
v20.18.1C:\>nvs use 16
Specified version not found.
To add this version now: nvs add node/16C:\>nvs add node/16
Extracting [###########################################################################################] 100%
Added at: %LOCALAPPDATA%\nvs\node\16.20.2\x64\node.exe
To use this version now: nvs use node/16.20.2/x64C:\>npx create-wujie@latest
Need to install the following packages:
create-wujie@0.4.0
Ok to proceed? (y) y📦 Welcome To Create Template for WuJie! V0.3.2
√ Project name: ... wujie-main
√ What framework do you choose as your main application ? » Webpack + Vue2
√ Select the main application route pattern » history
√ What framework do you choose as your sub application ? » Vite, Vue2, Vue3, React16, React17
√ Select the sub application route pattern » history
安装完成以后,分别单独启动wujie的主应用,和子应用,记得将node的版本都统一设置为 16 这样就可以正常体验wujie官方提供的demo。
wujie代码分析 vue2主应用
import "whatwg-fetch"; // fetch polyfill
import "custom-event-polyfill"; // CustomEvent polyfillimport Vue from "vue";
import App from "./App.vue";
import router from "./router";
import WujieVue from "wujie-vue2";
import hostMap from "../wujie-config/hostMap";
import credentialsFetch from "../wujie-config/fetch";
import Switch from "ant-design-vue/es/switch";
import Tooltip from "ant-design-vue/es/tooltip";
import button from "ant-design-vue/es/button/index";
import Icon from "ant-design-vue/es/icon/index";
import "ant-design-vue/es/button/style/index.css";
import "ant-design-vue/es/style/index.css";
import "ant-design-vue/es/switch/style/index.css";
import "ant-design-vue/es/tooltip/style/index.css";
import "ant-design-vue/es/icon/style/index.css";
import lifecycles from "../wujie-config/lifecycle";
import plugins from "../wujie-config/plugin";const isProduction = process.env.NODE_ENV === "production";
const { setupApp, preloadApp, bus } = WujieVue;
Vue.use(WujieVue).use(Switch).use(Tooltip).use(button).use(Icon);Vue.config.productionTip = false; // 关闭生产提示bus.$on("click", (msg) => window.alert(msg));// 在 xxx-sub 路由下子应用将激活路由同步给主应用,主应用跳转对应路由高亮菜单栏
bus.$on("sub-route-change", (name, path) => {const mainName = `${name}-sub`;const mainPath = `/${name}-sub${path}`;const currentName = router.currentRoute.name;const currentPath = router.currentRoute.path;if (mainName === currentName && mainPath !== currentPath) {router.push({ path: mainPath });}
});// 根据浏览器的版本,如果不支持 Proxy,则降级 Object.defineProperty 如果不支持webcomponent 则降级iframe 理论上可以兼容到 IE 9
const degrade =window.localStorage.getItem("degrade") === "true" ||!window.Proxy ||!window.CustomElementRegistry;const props = {// 将主应用的router.push方法传递给子应用,这样子应用就能通过获取jump方法,来控制主应用的跳转jump: (name) => {router.push({ name });},
};
/*** 大部分业务无需设置 attrs* 此处修正 iframe 的 src,是防止github pages csp报错* 因为默认是只有 host+port,没有携带路径*/
const attrs = isProduction ? { src: hostMap("//localhost:8000/") } : {};
/*** 配置应用,主要是设置默认配置* preloadApp、startApp的配置会基于这个配置做覆盖*/setupApp({name: "react16",url: hostMap("//localhost:7600/"),attrs,exec: true,props, // 给子应用传递的参数fetch: credentialsFetch,plugins,// prefix 用于改变子路径过长,在主应用中进行替换prefix: { "prefix-dialog": "/dialog", "prefix-location": "/location" },degrade,...lifecycles,
});setupApp({name: "react17",url: hostMap("//localhost:7100/"),attrs,exec: true, //是否预先执行子应用alive: true, // 是否保存子应用的状态props,fetch: credentialsFetch,degrade,...lifecycles,
});
setupApp({name: "vue2",url: hostMap("//localhost:6100/"),attrs,exec: true,props,fetch: credentialsFetch,degrade,...lifecycles,
});setupApp({name: "vue3",url: hostMap("//localhost:8082/"),attrs,exec: true,alive: true,plugins: [{cssExcludes: ["https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css",],},],props,// 引入了的第三方样式不需要添加credentialsfetch: (url, options) =>url.includes(hostMap("//localhost:8082/"))? credentialsFetch(url, options): window.fetch(url, options),degrade,...lifecycles,
});
setupApp({name: "vite",url: hostMap("//localhost:8083/"),attrs,exec: true,props,fetch: credentialsFetch,degrade,...lifecycles,
});// 因为已经setupApp注册了,这里可以简写,预加载只写name就可以了
if (window.localStorage.getItem("preload") !== "false") {preloadApp({name: "react16",});preloadApp({name: "react17",});preloadApp({name: "vue2",});if (window.Proxy) {preloadApp({name: "vue3",});preloadApp({name: "vite",});}
}new Vue({router,render: (h) => h(App),
}).$mount("#app");
主应用中,用来显示子应用的配置
wujieVue这个组件只要url一变化,在非保活模式下,子应用就会重新加载
<template><!--保活模式,name相同则复用一个子应用实例,改变url无效,必须采用通信的方式告知路由变化 --><WujieVue width="100%" height="100%" name="react17" :url="react17Url"></WujieVue>
</template><script>
import hostMap from "../../wujie-config/hostMap";
import wujieVue from "wujie-vue2"; // 引入wujie-vue2,如果是vue3请引入wujie-vue3 用来显示子应用
export default {data() {return {react17Url: hostMap("//localhost:7100/") + this.$route.params.path, //hostMap区分开发环境和生产环境};},watch: {// 保活模式,name相同则复用一个子应用实例,改变url无效,必须采用通信的方式告知路由变化"$route.params.path": {handler: function () {wujieVue.bus.$emit("react17-router-change", `/${this.$route.params.path}`);},immediate: true,},},
};
</script><style lang="scss" scoped></style>
非保活模式的子应用在主应用中的配置
<template><!--单例模式,name相同则复用一个无界实例,改变url则子应用重新渲染实例到对应路由 --><WujieVue width="100%" height="100%" name="vite" :url="viteUrl"></WujieVue>
</template><script>
import hostMap from "../../wujie-config/hostMap";export default {// 如果是非保活模式,不需要watch这个$route.params.path变化,并去调用wujieVue.bus.$emitcomputed: {viteUrl() {return hostMap("//localhost:8083/") + this.$route.params.path;},},
};
</script><style lang="scss" scoped></style>
vue2主应用,路由的配置
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Multiple from "../views/Multiple.vue";
import Vue2 from "../views/Vue2.vue";
import Vue2Sub from "../views/Vue2-sub.vue";
import Vue3 from "../views/Vue3.vue";
import Vue3Sub from "../views/Vue3-sub.vue";
import Vite from "../views/Vite.vue";
import ViteSub from "../views/Vite-sub.vue";
import React16 from "../views/React16.vue";
import React16Sub from "../views/React16-sub.vue";
import React17 from "../views/React17.vue";
import React17Sub from "../views/React17-sub.vue";const basename = process.env.NODE_ENV === "production" ? "/demo-main-vue/" : ""; // 区分不同环境下,资源所在的不同文件夹
Vue.use(VueRouter);const routes = [{path: "/all",name: "all",component: Multiple,},{path: "/",redirect: "/home",},{path: "/home",name: "home",component: Home,},{path: "/vue2",name: "vue2",component: Vue2,},{path: "/vue2-sub/:path",name: "vue2-sub",component: Vue2Sub,},{path: "/vue3",name: "vue3",component: Vue3,},{path: "/vue3-sub/:path",name: "vue3-sub",component: Vue3Sub,},{path: "/vite",name: "vite",component: Vite,},{path: "/vite-sub/:path",name: "vite-sub",component: ViteSub,},{path: "/react16",name: "react16",component: React16,},{path: "/react16-sub/:path",name: "react16-sub",component: React16Sub,},{path: "/react17",name: "react17",component: React17,},{path: "/react17-sub/:path",name: "react17-sub",component: React17Sub,},
];// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置const router = new VueRouter({mode: "history",base: basename,routes,
});export default router;
vue2主应用vue.config 配置
// vue.config.js/*** @type {import('@vue/cli-service').ProjectOptions}*/
module.exports = {publicPath: process.env.NODE_ENV === "production" ? "/demo-main-vue/" : "/", // 区分开发和生产服务器的路径devServer: {headers: {"Access-Control-Allow-Origin": "*", // 如果需要跨域,请打开此配置},open: process.env.NODE_ENV === "development", // 只有开发环境需要使用devServerport: "8000",},lintOnSave: false // 是否关闭eslint检查,只在保存时才检查
};
react子应用代码分析
子应用可以用到的wujie的数据 https://wujie-micro.github.io/doc/api/wujie.html#VPSidebarNav
import "react-app-polyfill/stable";
import "react-app-polyfill/ie11";import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";
import "./styles.css";const basename = process.env.NODE_ENV === "production" ? "/demo-react16/" : "";// 如果作为无界的子应用打开,就需要使用 window.__POWERED_BY_WUJIE__ 判断,然后挂载函数__WUJIE_MOUNT和卸载函数__WUJIE_UNMOUNT
if (window.__POWERED_BY_WUJIE__) {// eslint-disable-next-line no-undefwindow.__WUJIE_MOUNT = () => {ReactDOM.render(<Router basename={basename}><App /></Router>,document.getElementById("root"));};window.__WUJIE_UNMOUNT = () => {ReactDOM.unmountComponentAtNode(document.getElementById("root"));};
} else {ReactDOM.render(<Router basename={basename}><App /></Router>,document.getElementById("root"));
}
react 子应用,嵌套其他子应用
import React from "react";
import WujieReact from "wujie-react"; // 需要引入的wujie react 组件
import lifecycles from "./lifecycle"; // 对应的生命周期
import hostMap from "./hostMap"; // 对应的一些开发环境和生产环境的host映射function selfFetch(url, options) {const includeFlag = process.env.NODE_ENV === "production";return window.fetch(url, { ...options, credentials: includeFlag ? "include" : "omit" });
}export default function React17() {const react17Url = hostMap("//localhost:7100/");const degrade = window.localStorage.getItem("degrade") === "true";const props = {jump: (name) => {window?.$wujie.props.jump(name); // 从主应用vue2中得到的改变主应用router的函数jump,再传递给嵌套的子应用},};return (<div><h2>子应用嵌套</h2><div className="content" style={{ border: "1px dashed #ccc", overflow: "auto" }}><WujieReactwidth="100%"height="500px"name="react17"url={react17Url}alive={true}sync={true}fetch={selfFetch}props={props}degrade={degrade}beforeLoad={lifecycles.beforeLoad}beforeMount={lifecycles.beforeMount}afterMount={lifecycles.afterMount}beforeUnmount={lifecycles.beforeUnmount}afterUnmount={lifecycles.afterUnmount}></WujieReact></div></div>);
}
子应用可能还会遇到的问题
无界快速上手 https://wujie-micro.github.io/doc/guide/start.html
相关文章:
微前端 无界wujie
开发环境配置: Node.js 版本 < 18.0.0 pnpm 脚手架示例模版基于 pnpm turborepo 管理项目 如果您的当前环境中需要切换 node.js 版本, 可以使用 nvm or fnm 进行安装. 以下是通过 nvm 或者nvs 安装 Node.js 16 LTS 版本 nvs安装教程 https://blog.csdn.net/glorydx/artic…...
Linux应用:程序运行
kill kill命令的这种用法是向指定的进程发送特定信号编号的信号。信号在操作系统中是一种软件中断机制,用于通知进程发生了某种特定事件或要求进程执行特定操作。 kill - 信号编号 进程 ID 信号编号的含义:不同的信号编号代表不同的事件或操作。例如…...
【公务员考试】高效备考指南
高效备考指南:从计划制定到心态调整的全面攻略 公务员考试竞争激烈,备考过程既需要科学规划,也需要持之以恒的努力。结合多位高分考生的经验与专业机构的指导,本文整理了一套系统化的备考策略,涵盖目标设定、学习方法…...
基于SpringBoot+Vue3实现的宠物领养管理平台功能一
一、前言介绍: 1.1 项目摘要 随着社会经济的发展和人们生活水平的提高,越来越多的人开始关注并参与到宠物领养中。宠物已经成为许多家庭的重要成员,人们对于宠物的关爱和照顾也日益增加。然而,传统的宠物领养流程存在诸多不便&a…...
ens33没有分配到IPV4问题
方法一:手动为 ens33 接口分配 IP 地址 你能够借助 ip 命令手动给 ens33 接口分配 IP 地址。不过这种方式在系统重启之后就会失效。 步骤 查看网络信息 先查看一下当前网络的子网信息,例如网关地址和子网掩码等,你可以通过路由器管理界面或…...
SpringCloud 学习笔记2(Nacos)
Nacos Nacos 下载 Nacos Server 下载 | Nacos 官网 下载、解压、打开文件: 更改 Nacos 的启动方式 Nacos 的启动模式默认是集群模式。在学习时需要把他改为单机模式。 把 cluster 改为 standalone,记得保存! 启动startup.cmd Ubuntu 启动…...
Blender-MCP服务源码4-初始化项目解读
Blender-MCP服务源码4-初始化项目解读 上篇文章针对Blender开发框架完成了一个基础模板的搭建,并在Blender中成功进行了运行,那这个初始化项目中是如何进行页面效果呈现的,尝试手动进行功能精简来拆解项目代码 1-核心知识点 1)如…...
基于eNSP的IPV4和IPV6企业网络规划
基于eNSP的IPV4和IPV6企业网络规划 前言网络拓扑设计功能设计技术详解一、网络设备基础配置二、虚拟局域网(VLAN)与广播域划分三、冗余协议与链路故障检测四、IP地址自动分配与DHCP相关配置五、动态路由与安全认证六、广域网互联及VPN实现七、网络地址转…...
Vue3项目中可以尝试封装那些组件
在 Vue 3 项目中,组件的封装可以根据功能、复用性和业务需求进行划分。以下是一些常见的组件类型,适合封装为独立组件: 1. 基础 UI 组件 按钮 (Button) 封装不同样式、大小、状态的按钮。支持 disabled、loading 等状态。 输入框 (Input) 封…...
Web Component 教程(二):如何有效管理和使用自定义属性
前言 在现代前端开发中,Web Component 是一个强大的工具,可以帮助我们创建可重用的组件。Web Component 的一个重要特性是能够处理自定义属性,这使得我们能够灵活地控制组件的行为和外观。今天,我会通过一个通俗易懂的教程&#…...
C#特性和反射
1。特性概念理解? 特性(Attribute)是用于在【运行时】传递程序中各种元素(比如类、属性、方法、结构、枚举、组件等)行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所…...
蓝桥杯刷题周计划(第三周)
目录 前言题目一题目代码题解分析 题目二题目代码题解分析 题目三题目代码题解分析 题目四题目代码题解分析 题目五题目代码题解分析 题目六题目代码题解分析 题目七题目代码题解分析 题目八题目代码题解分析 题目九题目代码题解分析 题目十题目代码题解分析 前言 大家好&#…...
mysql5.x和mysql8.x查看和设置隔离级别
MySQL的隔离级别 级别标志值描述读未提交READ-UNCOMMITTED0存在脏读、不可重复读、幻读的问题读已提交READ-COMMITTED1解决脏读的问题,存在不可重复读、幻读的问题可重复读REPEATABLE-READ2mysql 默认级别,解决脏读、不可重复读的问题,存在幻…...
3.17学习总结
写了两道题 刚开始用的之前做组合输出的方法,时间超限了,想不出怎么优化,后面看了题解,代码如下 #include <stdio.h> #include <stdlib.h> int n,min2e9; int a[11],b[11]; //搜索 void hly(int s,int x,int y) {//当…...
Blender材质 - 层权重
层权重 混合着色器 可以让 面朝向的一面显示一种材质 另一面显示另一种材质 就能实现挺不错的材质效果 移动视角 材质会跟着变化 有点类似虚幻的视差节点BumpOffset...
【JavaEE】Spring Boot 日志
目录 一、日志概述二、使用日志2.1 打印日志2.2 日志框架2.2.1 门面 / 外观 模式 2.3 日志级别2.3.1 六大分类2.3.2 使用 2.4 日志级别配置2.5 日志的持久化2.6 日志文件分割2.7 日志文件格式2.8 Slf4j 简单打印日志 一、日志概述 ⽇志主要是为了发现问题, 分析问题, 定位问题…...
Qt中的 #include “xxxx.moc“ 说明
Qt中的 #include “xxxx.moc” 说明 在Qt开发中,有时会看到在cpp文件末尾包含 #include "xxxx.moc" 这样的代码。这种做法主要用于以下情况: 使用场景 当你在非头文件中定义了一个包含Q_OBJECT宏的类时,需要包含对应的.moc文件。…...
如何用solidworks画齿轮
齿轮还是很有技术含量的,专业名词太多看不懂, 只会画 (这个东西不能自己想当然画, 齿轮之间不啮合是很有问题的,会积累磨损) 步骤1 打开设计库里的toolbox 选择正齿轮,右键生成零件 需要改的有几个关键的地方,我是只知道内圆外圆所以,对我来说最重要的是标称轴直径 (即正中间…...
详解布隆过滤器及其模拟实现
目录 布隆过滤器 引入 概念 工作原理 模拟实现布隆过滤器 哈希函数集 布隆过滤器基本框架 add函数(添加到布隆过滤器中) contains函数(判断是否存在该值) 完整代码 布隆过滤器的删除 布隆过滤器的误判率 布隆过滤器的…...
element-plus中DatePicker 日期选择器组件的使用
1.选择某一天 代码: <el-date-pickerv-model"invoice_date"type"date"placeholder"请选择日期"style"width: 200px;"clearable /> 运行效果: 问题所在:这个数据的格式不是我们后端需要的那种&…...
SvelteKit 最新中文文档教程(4)—— 表单 actions
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
力扣hot100二刷——二叉树
第二次刷题不在idea写代码,而是直接在leetcode网站上写,“逼”自己掌握常用的函数。 标志掌握程度解释办法⭐Fully 完全掌握看到题目就有思路,编程也很流利⭐⭐Basically 基本掌握需要稍作思考,或者看到提示方法后能解答⭐⭐⭐Sl…...
企业安全——数据泄露防护
0x00 前言 本篇对数据泄露防护方面的内容进行汇总和总结,为抛砖引玉的内容 0x01 数据隔离 数据隔离是防止数据泄露的一个非常好的方式,通常的隔离方式有 主机/服务器隔离网络隔离介质隔离 0x02 数据丢失预防 主要防止数据丢失的方法就是DLP&#x…...
字符串哈希从入门到精通
一、基本概念 字符串哈希是将任意长度的字符串映射为固定长度的哈希值(通常为整数)的技术,核心目标是实现O(1)时间的子串快速比较和高效查询。其本质是通过数学运算将字符串转换为唯一性较高的数值,例如: …...
C语言:编程设计猜数游戏
先由计算机想一个数给用户猜,如果猜对了,提示“right!”,猜错了,提示“wrong!及大小” 思路:用随机函数rand()取到计算机想的数 代码: #include <stdio.…...
地下车库智能停车位指引系统方案(还有缺陷)
一、系统核心技术架构 通过车牌识别+车位检测+室内定位+路径规划四大技术模块实现全自动指引: 二、关键技术方案 1. 车辆身份识别与入场触发 车牌识别(LPR)技术 入口处部署高清摄像头,自动识别车牌并关联车辆信息(如会员、临时车)。触发逻辑:识别成功后抬杆放行,同时…...
Docker 使用指南
Docker 是一种开源的容器化平台,它通过使用容器来进行应用程序的打包、分发和部署。下面是 Docker 的基本概念和优势: 容器化:Docker 使用容器来封装应用程序及其所有依赖项,使其能够在任何环境中运行,并且与底层系统隔…...
win10 c++ VsCode 配置PCL open3d并显示
win10 c VsCode配置PCL open3d并显示 一、效果图二、配置步骤2.1 安装vscode2.2 pcl-open3d配置2.3 vscode中设置 三、测试代码四、注意事项及后续 一、效果图 二、配置步骤 2.1 安装vscode vscode下载链接 下载中文插件、c相关插件 2.2 pcl-open3d配置 1)下载…...
Vala 开发环境搭建
介绍 Vala 是一种使用现代高级抽象的编程语言,与用 C 语言编写的应用程序和库相比,没有施加额外的运行时要求,也不需要使用不同的 ABI。 Vala 使用 GObject 类型系统,并具有额外的代码生成例程,使面向 GNOME 堆栈变得简…...
【网页】自制流光卡片
概述 小红书有个博主自己搞的笔记排版工具叫“流光卡片”,类似的还有个Markdown排版工具叫MD2Card。 我这个版本类似,但是自己写的东西,控制性更好。 初期就写了个静态页面,后期结合Godot快速生成,并可能结合JS库&a…...
