# federation使用场景和样例说明
# 简介和项目改法
简介 Jsview-vue-federation 是一种host remote架构的,子模块(remote)独立打包,可动态加载的模式,区别于jsview-vue模式下,工程内容所有模块最总打包在一起一起输出的老模式。
现有工程改造成remote/host 对于已有的jsview-vue工程,
改造成host时:
npm run tool -- --module-federation --mode=host --jsview=shared -remote-domain=http://localhost:8088
改造成remote时:
npm run tool -- --module-federation --mode=remote --jsview=shared
以上的tool指令都会包含install指令:
npm install @originjs/vite-plugin-federation@1.3.4
但是不包含
npm run tool -- --config-app && npm run tool -- --gen-keypair
# 场景1: 子模块动态上线
用于活动组件做成动态上线的子模块,主模块EPG界面按需进行动态加载的场景。
可用的公开demo: https://gitlab.cluster.qcast.cn/mirror/jsview-vue-federation-demo.git
目录: host-remote-run
子模块(remote-app) 用来包装活动组件。一般是把所有活动打包到一个主入口中。也可以打包成多个remote工程,但是host那边需要针对每个remote配置一个引用入口(在host的federation.host.config.ts的remotes字段配置)。
关注内容见git中,host-remote-run/remote-app的README1. remote的App.vue的所有jsview模块必须来源于 HostJsvShared.js, 此文件和 host 端共用一份
后续增加时,需要host那边先改,然后把文件发给remote使用,并且remote运行在改完文件的host上才有这些模块可使用
2. remote的vite.config.js中有如下处理,防止代码中误用 import {xxx} from 'jsview' 的写法
'jsview': '', // 取消jsview的引用名
3. federation.remote.config中的expose中的命名(MindMapMainApp)要和host端进行约定,用于host端对本模块引用主模块(host-app) 为主EPG的代码工程host化。 关注内容见git中,host-remote-run/remote-app的README
1. 加载remote模块通过 App.vue 的 defineAsyncComponent 来完成,模块名字(MindMapMainApp)与remote进行约定即可。
2. defineAsyncComponent 调用中,通过 JsvFederationTools.alterModuleUrl 定义远程模块服务器位置。注意: 此alterModuleUrl接口只有模块未被加载时才能使用,加载后使用则无效。
3. HostJsvShared.js的内容为共享给remote的jsview模块,没写到这里面的内容,remote无法使用。后续增加时,需要host那边先改,然后把文件发给remote使用,并且remote运行在改完文件的host上才有这些模块可使用。
4. 远程入口可以是单个也可以是多个,每个remote(独立打包的工程)要对应一个入口(但单个remote可以有多个子模块),需要federation.host.config.ts的remotes资源来配置。
# 场景2: 子模块联调不开源的主模块
用于主模块不方便开源,但子模块调试时,和主模块有强烈的依存关系的场景,此场景,主模块临时改造成remote模块,供子模块作为工作环境启动起来,然后子模块调试时,启动remote主模块前,先把自己调试模块动态注入到全局中,在主模块启动时优先使用全局的注入模块以达到子模块的内容为npm start对应内容的调试目的。 可用的公开demo: https://gitlab.cluster.qcast.cn/mirror/jsview-vue-federation-demo.git 目录: debug-sub-module
主模块(main-module, 作为remote) 主模块修改为优先使用全局注入的子模块的逻辑。对于router跳转子模块的场景,可以参考以下单remote内含多子模块的代码:
import blank from "./blank.vue" routerList { import("../../node modules/sub-provider/indexProxy.js").newEntry1?blank import("../../node modules/sub-provider/indexProxy.js").newEntry2?blank import("../../node modules/sub-provider/indexProxy.js").newEntry3?blank }
1
2
3
4
5
6其余关注内容见git中,debug-sub-module/main-module的README
1. 加载调试模块时,并不是直接加载,而是通过proxy加载,例如 itemProxy.js,在此Proxy中,判断是否存在注入内容(window.WrapItem),无注入则用自己代码中的模块。
2. federation.remote.config中的expose中的命名(MainModule)要和host端进行约定,用于host端对本模块引用。子模块(sub-module-debug,作为host) 目的是将main.tsx引入的App.vue的第一个入口替换成remote提供的主模块的App.vue,并在异步加载前全局声明本调试子模块。 其余关注内容见git中,debug-sub-module/main-module的README
1. 使用 JsvFederationTools.alterModuleUrl 将remote加载地址指向服务器
2. App.vue通过 defineAsyncComponent 对主场景(main-module)的app.vue进行引入,
加载内容"RemoteEntry/MainModule"与主场景 federation.remote.config.js 的 exposes 相呼应
3. 在 defineAsyncComponent 进行加载前, 通过 window.WrapItem 把主场景中的模块代码替换(注入) 成本地调试代码(DebugItem.vue),此处理和 main-module 的ItemProxy对window.WrapItem的处理相呼应
4. 在template中只是使用 defineAsyncComponent => AsyncComp 内容来展示主场景