微前端 無界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.pswp.cn/pingmian/72643.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72643.shtml
英文地址,請注明出處:http://en.pswp.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