test: 测试无界降级加载渲染器

This commit is contained in:
wangxuefeng
2025-03-18 15:16:59 +08:00
parent d1cbb3f1f7
commit 6c1c8b87a4
8 changed files with 1451 additions and 40 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -31,7 +31,8 @@
"licia-es": "catalog:", "licia-es": "catalog:",
"postmate": "catalog:", "postmate": "catalog:",
"rrweb": "2.0.0-alpha.4", "rrweb": "2.0.0-alpha.4",
"vue": "catalog:" "vue": "catalog:",
"vue-router": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"@farmfe/cli": "catalog:", "@farmfe/cli": "catalog:",

View File

@@ -8,13 +8,6 @@ import { ElLoading, ElMessage } from 'element-plus';
import { LowCodeService } from './service'; import { LowCodeService } from './service';
// 解析 url 参数
const urlParams = new URLSearchParams(window.location.search);
const fileId = urlParams.get('fileId');
console.log('urlParams-fileId', fileId);
const projectId = urlParams.get('projectId');
console.log('urlParams-projectId', projectId);
// 定义 wujie props 的类型 // 定义 wujie props 的类型
interface WujieProps { interface WujieProps {
accessToken?: string; accessToken?: string;

View File

@@ -0,0 +1,168 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted } from 'vue';
import WujieVue from 'wujie-vue3';
import { version } from '/package.json';
const props = defineProps<{
[key: string]: any;
accessToken?: string;
applicationId: number | string;
degrade?: boolean;
fileId: number | string;
name: string;
projectId: number | string;
sync: boolean;
url: string;
}>();
console.log('props', props);
const { bus } = WujieVue;
// 生命周期钩子
const beforeLoad = (appWindow: Window) => {
console.log(`${props.name} 开始加载`, appWindow);
};
const afterMount = (appWindow: Window) => {
console.log(`${props.name} 加载完成`, appWindow);
};
// 事件处理
const handleMessage = (data: any) => {
console.log('收到子应用消息:', data);
};
// 准备传递给子应用的数据
const subAppProps = {
...props,
adapterInfo: {
version,
},
};
// 监听子应用的事件
const handleReady = (data: any) => {
console.log('子应用就绪:', data);
// 可以在这里执行一些操作
};
const handleRenderSuccess = () => {
console.log('子应用渲染成功');
// 通知父应用
};
const handleRenderFail = (error: any) => {
console.error('子应用渲染失败:', error);
// 处理错误情况
};
onMounted(() => {
// 注册事件监听
bus.$on('message', handleMessage);
bus.$on('ready', handleReady);
bus.$on('render-success', handleRenderSuccess);
bus.$on('render-fail', handleRenderFail);
});
onBeforeUnmount(() => {
// 移除所有事件监听
bus.$off('message', handleMessage);
bus.$off('ready', handleReady);
bus.$off('render-success', handleRenderSuccess);
bus.$off('render-fail', handleRenderFail);
});
// 在子应用加载前执行的脚本,用于修补 adoptedStyleSheets
const execBeforeLoading = `
// 修补 CSSStyleSheet API
if (window.CSSStyleSheet && CSSStyleSheet.prototype.replaceSync) {
const originalReplaceSync = CSSStyleSheet.prototype.replaceSync;
CSSStyleSheet.prototype.replaceSync = function(text) {
try {
return originalReplaceSync.call(this, text);
} catch (e) {
console.warn('CSSStyleSheet.replaceSync 被拦截:', e);
// 降级处理:创建普通样式标签
const style = document.createElement('style');
style.textContent = text;
document.head.appendChild(style);
return null;
}
};
}
// 替换 adoptedStyleSheets 的 setter
try {
if (Document.prototype.hasOwnProperty('adoptedStyleSheets')) {
const descriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'adoptedStyleSheets');
if (descriptor && descriptor.set) {
const originalSetter = descriptor.set;
descriptor.set = function(sheets) {
try {
originalSetter.call(this, sheets);
} catch (e) {
console.warn('adoptedStyleSheets setter 被拦截:', e);
// 不抛出错误,静默失败
}
};
Object.defineProperty(Document.prototype, 'adoptedStyleSheets', descriptor);
}
}
} catch (e) {
console.warn('无法修补 adoptedStyleSheets:', e);
}
`;
</script>
<template>
<div style="width: 100%; height: 100%">
<WujieVue
:name="name"
:url="url"
:sync="sync"
:degrade="degrade"
width="100%"
height="100%"
:props="subAppProps"
:before-load="beforeLoad"
:after-mount="afterMount"
:plugins="[
{
cssLoader: (code, url, jsdom, appWindow) => {
console.log('cssLoader', code, url, jsdom, appWindow);
try {
// 尝试在子应用窗口中创建样式
if (appWindow && appWindow.document) {
const style = appWindow.document.createElement('style');
style.textContent = code;
appWindow.document.head.appendChild(style);
return true;
}
// 如果没有 appWindow尝试使用 jsdom
if (jsdom && jsdom.window && jsdom.window.document) {
const style = jsdom.window.document.createElement('style');
style.textContent = code;
jsdom.window.document.head.appendChild(style);
return true;
}
// 都不可用时,返回 false 让 wujie 使用默认处理
return false;
} catch (error) {
console.warn('CSS 处理错误:', error);
return false; // 让 wujie 使用默认处理
}
},
},
]"
:degrade="true"
:exec-before-loading="execBeforeLoading"
/>
</div>
</template>

View File

@@ -0,0 +1,93 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted } from 'vue';
import WujieVue from 'wujie-vue3';
import { version } from '/package.json';
const props = defineProps<{
[key: string]: any;
accessToken?: string;
applicationId: number | string;
degrade?: boolean;
fileId: number | string;
name: string;
projectId: number | string;
sync: boolean;
url: string;
}>();
console.log('props', props);
const { bus } = WujieVue;
// 生命周期钩子
const beforeLoad = (appWindow: Window) => {
console.log(`${props.name} 开始加载`, appWindow);
};
const afterMount = (appWindow: Window) => {
console.log(`${props.name} 加载完成`, appWindow);
};
// 事件处理
const handleMessage = (data: any) => {
console.log('收到子应用消息:', data);
};
// 准备传递给子应用的数据
const subAppProps = {
...props,
adapterInfo: {
version,
},
};
// 监听子应用的事件
const handleReady = (data: any) => {
console.log('子应用就绪:', data);
// 可以在这里执行一些操作
};
const handleRenderSuccess = () => {
console.log('子应用渲染成功');
// 通知父应用
};
const handleRenderFail = (error: any) => {
console.error('子应用渲染失败:', error);
// 处理错误情况
};
onMounted(() => {
// 注册事件监听
bus.$on('message', handleMessage);
bus.$on('ready', handleReady);
bus.$on('render-success', handleRenderSuccess);
bus.$on('render-fail', handleRenderFail);
});
onBeforeUnmount(() => {
// 移除所有事件监听
bus.$off('message', handleMessage);
bus.$off('ready', handleReady);
bus.$off('render-success', handleRenderSuccess);
bus.$off('render-fail', handleRenderFail);
});
</script>
<template>
<div style="width: 100%; height: 100%">
<WujieVue
:name="name"
:url="url"
:sync="sync"
:degrade="true"
width="100%"
height="100%"
:props="subAppProps"
:before-load="beforeLoad"
:after-mount="afterMount"
/>
</div>
</template>

View File

@@ -17,9 +17,9 @@ const props = defineProps<{
url: string; url: string;
}>(); }>();
console.log('props', props); const { bus, preloadApp } = WujieVue;
const { bus } = WujieVue; console.log('props', props);
// 生命周期钩子 // 生命周期钩子
const beforeLoad = (appWindow: Window) => { const beforeLoad = (appWindow: Window) => {
@@ -30,9 +30,9 @@ const afterMount = (appWindow: Window) => {
console.log(`${props.name} 加载完成`, appWindow); console.log(`${props.name} 加载完成`, appWindow);
}; };
// 事件处理 // 定义自定义 fetch 函数
const handleMessage = (data: any) => { const customFetch = (url: string, options?: any) => {
console.log('收到子应用消息:', data); return window.fetch(url, { ...options, credentials: 'include' });
}; };
// 准备传递给子应用的数据 // 准备传递给子应用的数据
@@ -43,52 +43,51 @@ const subAppProps = {
}, },
}; };
// 监听子应用的事件 // 预加载应用
const handleReady = (data: any) => {
console.log('子应用就绪:', data);
// 可以在这里执行一些操作
};
const handleRenderSuccess = () => {
console.log('子应用渲染成功');
// 通知父应用
};
const handleRenderFail = (error: any) => {
console.error('子应用渲染失败:', error);
// 处理错误情况
};
onMounted(() => { onMounted(() => {
// 注册事件监听 // 注册事件监听
bus.$on('message', handleMessage); bus.$on('message', (data: any) => {
bus.$on('ready', handleReady); console.log('收到子应用消息:', data);
bus.$on('render-success', handleRenderSuccess); });
bus.$on('render-fail', handleRenderFail); bus.$on('ready', (data: any) => {
console.log('子应用就绪:', data);
});
bus.$on('render-success', () => {
console.log('子应用渲染成功');
});
bus.$on('render-fail', (error: any) => {
console.error('子应用渲染失败:', error);
});
// 预加载应用
preloadApp({
degrade: true,
exec: true,
fetch: customFetch,
name: props.name,
url: props.url,
});
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
// 移除所有事件监听 // 移除所有事件监听
bus.$off('message', handleMessage); bus.$offAll();
bus.$off('ready', handleReady);
bus.$off('render-success', handleRenderSuccess);
bus.$off('render-fail', handleRenderFail);
}); });
</script> </script>
<template> <template>
<div style="width: 100%; height: 100%"> <div style="width: 100%; height: 100%">
<WujieVue <WujieVue
:id="name"
:key="name"
:name="name" :name="name"
:url="url" :url="url"
:sync="sync" :sync="sync"
:degrade="degrade" :degrade="true"
width="100%" width="100%"
height="100%" height="100%"
:props="subAppProps" :props="subAppProps"
:before-load="beforeLoad" :before-load="beforeLoad"
:after-mount="afterMount" :after-mount="afterMount"
:fetch="customFetch"
/> />
</div> </div>
</template> </template>

3
pnpm-lock.yaml generated
View File

@@ -904,6 +904,9 @@ importers:
vue: vue:
specifier: ^3.5.13 specifier: ^3.5.13
version: 3.5.13(typescript@5.8.2) version: 3.5.13(typescript@5.8.2)
vue-router:
specifier: 'catalog:'
version: 4.5.0(vue@3.5.13(typescript@5.8.2))
devDependencies: devDependencies:
'@farmfe/cli': '@farmfe/cli':
specifier: 'catalog:' specifier: 'catalog:'