微前端 无界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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/72643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跟网型逆变器小干扰稳定性分析与控制策略优化simulink仿真模型和代码(包含完整仿真报告)

关注&#xff1a;“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2016Rb&#xff09;软件。建议采用matlab2016 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff09; 近年来&#xff0c…

基于SpringBoot的“城市公交查询系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“城市公交查询系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面 用户登录界面 公…

框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性

最近在思考一个问题&#xff1a;如何能够更好的分享主流框架源码学习笔记&#xff08;主要是源码部分&#xff09;?让有缘刷到的同学既可以有所收获&#xff0c;还能保持对相关技术架构探讨学习热情和兴趣。以及自己也保持较高的分享热情和动力。 今天尝试用一个SQL查询作为引…

UNI-APP uts插件 支持ANDROID 监听手机状态

插件地址 https://ext.dcloud.net.cn/plugin?id22646 模块 import {startPhoneListener,stopPhoneListener,checkIsAutoRecord,toCallAutoRecorderPage,navigateToCallRecordingSettings,jumpToPermissionPage,makePhoneCall,allRecorderFilesAction,registerSmsReceiver,} f…

windows协议不再续签,华为再无windows可用,将于四月发布鸿蒙PC

大家好&#xff0c;我是国货系创始人张云泽&#xff0c;最近不少小伙伴在后台问&#xff1a;“听说Windows协议要到期了&#xff1f;我的电脑会不会变砖&#xff1f;”还有人说&#xff1a;“华为笔记本以后用不了Windows了&#xff1f;鸿蒙系统能用吗&#xff1f;”今天咱们就…

Stable Diffusion API /sdapi/v1/txt2img的完整参数列表及其说明

基本参数 {"prompt": "高质量&#xff0c;精细的恐龙", // 主提示词"negative_prompt": "模糊&#xff0c;低质量", // 负面提示词"styles": ["photorealistic", "detailed"], // 应用的风格预设&q…

TK矩阵:提高多账号管理效率的利器

随着TikTok的火爆&#xff0c;越来越多的人开始利用这个平台进行内容创作和社交互动。无论是个人创作者、品牌方&#xff0c;还是营销公司&#xff0c;TikTok都提供了巨大的机会&#xff0c;但同时也带来了运营上的挑战&#xff0c;尤其是在管理多个账户时。每个账号的维护、内…

关于Redis的集群(上)

目录 基本概念 数据分片算法 哈希求余 ​编辑一致性哈希算法 哈希槽分区算法 搭建集群环境 创建目录和配置 编写 docker-compose.yml 启动容器 构建集群 基本概念 广义的集群&#xff0c;只要是多个机器构成了分布式系统&#xff0c;都可以成为是一个“集群”。 但…

【CSS3】化神篇

目录 平面转换平移旋转改变旋转原点多重转换缩放倾斜 渐变线性渐变径向渐变 空间转换平移视距旋转立体呈现缩放 动画使现步骤animation 复合属性animation 属性拆分逐帧动画多组动画 平面转换 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配合使用 概念&#x…

Java 线程创建全解析:五种方式详细对比与实战示例

目录 Java 线程创建全解析&#xff1a;五种方式详细对比与实战示例一、引言二、创建线程的五种方式1. 继承 Thread 类2. 实现 Runnable 接口3. 匿名内部类实现 Thread4. 匿名内部类实现 Runnable5. 使用 Lambda 表达式&#xff08;Java 8及以上&#xff09; 三、线程创建方式对…

Dify平台离线镜像部署

Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过程中。 前提…

Unitest和pytest区别

1️⃣ 设计理念 ➡️ unittest &#xff1a; 是 Python 标准库的一部分&#xff0c;设计灵感来自 Java 的 JUnit&#xff0c;强调面向对象的测试模式。 测试用例需要继承 unittest.TestCase 类&#xff0c;测试方法以 test_ 开头。 更适合传统、结构化的测试开发方式。 ⭕ pyte…

GIT标签(Tag)操作

在Git中&#xff0c;标签&#xff08;Tag&#xff09;用于标记特定的提交点&#xff0c;通常用于发布版本。 切换到需要打标签的分支&#xff1a; git checkout <branch-name>创建标签 git tag v1.0.0 git tag -a v1.0.0 -m "Release version 1.0.0"查看所…

玩转github

me github 可以给仓库添加开发人员吗 4o 是的&#xff0c;GitHub允许仓库管理员为仓库添加开发人员&#xff0c;并设置这些开发人员的角色和权限。这里是一个简单的步骤指导&#xff0c;教你如何给一个 GitHub 仓库添加开发人员&#xff1a; 前提条件 你必须有这个仓库的权限&…

EDAS:投稿经验-word版本-问题解决

1. 字体不对&#xff0c;字体未嵌入问题 问题&#xff1a;word转PDF后&#xff0c;总是显示有字体格式不对&#xff08;忘记截图了&#xff09;。 办法&#xff1a;1. EDAS投稿PDF格式问题-CSDN博客-PDF上修改 IEEE论文检测的字体未嵌入问题Times New Ro…

如何在Django中有效地使用Celery进行定时任务?

当我们谈到Web开发时&#xff0c;Django无疑是一个非常流行的框架。而Celery则是与Django配合使用的强大任务队列工具。今天&#xff0c;我们来聊聊如何在Django中使用Celery来实现定时任务。定时任务在很多场景下都非常有用&#xff0c;比如定期发送邮件、清理数据库、执行数据…

声学建模中用于构音障碍语音识别的特征选择意义

声学建模中用于构音障碍语音识别的特征选择意义 原文:Significance of Feature Selection for Acoustic Modeling in Dysarthric Speech Recognition 引言 背景 构音障碍是由运动言语系统的神经损伤引起的,导致发音不清晰。自动语音识别系统对构音障碍语音无效,因其声学差…

【递归与动态规划(DP) C/C++】(1)递归 与 动态规划(DP)

- 第 82 篇 - Date: 2025 - 03 - 17 Author: 郑龙浩/仟濹 【递归与动态规划(DP) C/C】 文章目录 一 递归1基本介绍2 递归技巧**(1) 递归三步法****(2) 思维小技巧** 3 例题(1) 阶乘 (纯递归 or DP)(2) 斐波那契数列 (纯递归 or DP)(3) 汉诺塔 (纯递归 or DP)**① 英文打印过程…

eclipse运行配置,希望带参数该怎么配置

java -Dparam 在eclipse如何配置 在Eclipse中配置-Dparam这样的JVM参数&#xff0c;你可以按照以下步骤进行&#xff1a; 打开Eclipse。 选择菜单栏的"Run" -> "Run Configurations..."。 在弹出的"Run Configurations"窗口左侧&#xff0…

什么是 Fisher 信息矩阵

什么是 Fisher 信息矩阵 Fisher 信息矩阵是统计学和机器学习中一个重要的概念,它用于衡量样本数据所包含的关于模型参数的信息量。 伯努利分布示例 问题描述 假设我们有一个服从伯努利分布的随机变量 X X X,其概率质量函数为 P ( X