wujie框架应用(主子应用都是vite4+vue3)
改造
主应用中安装wujie的vue3组件
js
import WujieVue from 'wujie-vue3';
app.use(WujieVue);
import WujieVue from 'wujie-vue3';
app.use(WujieVue);
主应用改造
主应用的界面左侧是菜单栏,右侧是菜单的对应页面
主应用原先是采用动态组件的方式渲染右侧对应页面
js
<component
v-if="dynamicComponent"
:is="dynamicComponent"
></component>
<component
v-if="dynamicComponent"
:is="dynamicComponent"
></component>
js
let modules = import.meta.glob('../dynamicComponent/**/*.vue');
...
computed: {
/** 动态组件 */
dynamicComponent() {
let filename = this.currentNode.routerName;
...
return defineAsyncComponent(
modules[`../dynamicComponent/${filename}.vue`]
);
}
},
let modules = import.meta.glob('../dynamicComponent/**/*.vue');
...
computed: {
/** 动态组件 */
dynamicComponent() {
let filename = this.currentNode.routerName;
...
return defineAsyncComponent(
modules[`../dynamicComponent/${filename}.vue`]
);
}
},
现在把component
动态组件替换成wujie框架
不在主界面进行动态组件的渲染,而是拆分至子应用,把相应路径传递给子应用,子应用收到后进行动态组件的渲染,这样就可以自行拆分页面到相应子应用
js
<WujieVue
style="height: 100%"
name="vue3"
:url="vue3Url"
:plugins="plugins"
></WujieVue>
<WujieVue
style="height: 100%"
name="vue3"
:url="vue3Url"
:plugins="plugins"
></WujieVue>
js
/** 点击树节点也就是单个菜单时触发 */
handleNodeClick(data) {
...
wujieVue.bus.$emit('vue3-router-change', this.currentNode.routerName);
},
/** 点击树节点也就是单个菜单时触发 */
handleNodeClick(data) {
...
wujieVue.bus.$emit('vue3-router-change', this.currentNode.routerName);
},
子应用mounted
生命周期里渲染监听事件
子应用中再使用动态组件的方式渲染
js
<component
v-if="dynamicComponent"
:is="dynamicComponent"
></component>
<component
v-if="dynamicComponent"
:is="dynamicComponent"
></component>
mounted
生命周期里渲染监听事件,设置动态组件路径
js
mounted() {
window.$wujie?.bus.$on('vue3-router-change', (path) => {
this.wujie_dynamicComponent = path;
});
},
mounted() {
window.$wujie?.bus.$on('vue3-router-change', (path) => {
this.wujie_dynamicComponent = path;
});
},
js
let modules = import.meta.glob('../dynamicComponent/**/*.vue');
...
computed: {
/** 动态组件 */
dynamicComponent() {
if (this.wujie_dynamicComponent) {
return defineAsyncComponent(
modules[`../dynamicComponent/${this.wujie_dynamicComponent}.vue`]
);
}
},
let modules = import.meta.glob('../dynamicComponent/**/*.vue');
...
computed: {
/** 动态组件 */
dynamicComponent() {
if (this.wujie_dynamicComponent) {
return defineAsyncComponent(
modules[`../dynamicComponent/${this.wujie_dynamicComponent}.vue`]
);
}
},
注意点
主子应用共享localstorage,所以不用传token,用户信息到子应用
同样,要注意主子应用的localstorage的key不能重名,也不能随意localstorage.clear
多包运行库lerna
lerna
库可用于命令行方式进行多包管理
安装
sh
pnpm i -D @lerna-lite/cli @lerna-lite/run
pnpm i -D @lerna-lite/cli @lerna-lite/run
配置
lerna.json
npmClient 用于指定使用的包管理工具,用于lerna内部逻辑处理
version 字段是必须的
json
{
"npmClient": "pnpm",
"version": "0.0.1"
}
{
"npmClient": "pnpm",
"version": "0.0.1"
}
pnpm-workspace.yaml
Lerna 将使用 pnpm-workspace.yaml
解析包位置
js
packages:
- "packages/*"
packages:
- "packages/*"
package.json
根目录运行lerna run start
,将运行所有子包里的start
命令,从而可以一键启动所有子应用,打包同理
sh
"scripts": {
"start": "lerna run start --parallel",
...
},
"scripts": {
"start": "lerna run start --parallel",
...
},
尚未完成的改造
- 刷新完页面恢复到首页 (加localstorage保存dynamicComponent传参)
- 查漏补缺,完善dynamicComponent的页面传参
- 添加生产环境配置,现在还是开发环境的配置
基于lerna的monorepo改造现有项目实战总结
todo:隔离localstorage
html-loader
无界提供插件在运行时对子应用的 html 文本进行修改,使用该插件给所有子项目插入localstorage前缀
js
const plugins = [
{
// 对子应用的template进行的aaa替换成bbb
htmlLoader: (code) => {
return code.replace('aaa', 'bbb');
},
}
];
const plugins = [
{
// 对子应用的template进行的aaa替换成bbb
htmlLoader: (code) => {
return code.replace('aaa', 'bbb');
},
}
];
js-before-loaders
如果用户想在html
中所有的js
之前做,使用该插件给所有子项目插入localstorage前缀:
- 在子应用运行一个
src="http://xxxxx"
的脚本 - 在子应用中运行一个内联的 js 脚本
<script>content</script>
- 执行一个回调函数
那么这些工作可以放置在js-before-loaders
中进行
js
const plugins = [
{
// 在子应用所有的js之前
jsBeforeLoaders: [
// 插入一个外联脚本
{ src: "http://xxxx.js" },
// 插入一个内联监本
{ content: 'console.log("test")' },
// 执行一个回调,打印子应用名字
{
callback(appWindow) {
console.log("js-before-loader-callback", appWindow.__WUJIE.id);
},
},
],
},
];
const plugins = [
{
// 在子应用所有的js之前
jsBeforeLoaders: [
// 插入一个外联脚本
{ src: "http://xxxx.js" },
// 插入一个内联监本
{ content: 'console.log("test")' },
// 执行一个回调,打印子应用名字
{
callback(appWindow) {
console.log("js-before-loader-callback", appWindow.__WUJIE.id);
},
},
],
},
];
问题:子应用vite图片路径是主应用ip
https://github.com/Tencent/wujie/issues/398
实际上是vite问题,vite子应用打包图片使用的是self.location而不是i