feat(renderer): 悦码渲染器增加 sentry 做异常监听
This commit is contained in:
parent
22145b3893
commit
64b59a06a3
2
.npmrc
2
.npmrc
@ -1,4 +1,4 @@
|
||||
registry = "https://registry.npmmirror.com"
|
||||
registry = https://registry.npmmirror.com
|
||||
@sy:registry=http://sy-registry.shiyue.com
|
||||
public-hoist-pattern[]=husky
|
||||
public-hoist-pattern[]=eslint
|
||||
|
125
apps/docs/src/guide/integration/index.md
Normal file
125
apps/docs/src/guide/integration/index.md
Normal file
@ -0,0 +1,125 @@
|
||||
# 低代码渲染器接入指南
|
||||
|
||||
## 1. 概述
|
||||
|
||||
- 1.1 什么是低代码渲染器
|
||||
- 1.2 核心功能和优势
|
||||
- 1.3 适用项目
|
||||
- vue2
|
||||
- vue3
|
||||
- react
|
||||
- 其他框架请联系伊利(sy)或王雪峰(sy3570)添加适配器
|
||||
|
||||
## 2. 环境要求
|
||||
|
||||
- node >= 20
|
||||
- vue2 > 2.7.0
|
||||
- vue3 > 3.5.0
|
||||
- react > 18.0.0
|
||||
|
||||
## 3. 准备工作
|
||||
|
||||
1.npmrc 配置文件增加镜像指定,sy 组件库走 shiyue 源,其他走淘宝镜像
|
||||
|
||||
```bash
|
||||
registry=https://registry.npmmirror.com
|
||||
@sy:registry=http://sy-registry.shiyue.com
|
||||
```
|
||||
|
||||
2. node 至少要升级为 20 以上的版本
|
||||
|
||||
```bash
|
||||
nvm install 20
|
||||
nvm use 20
|
||||
```
|
||||
|
||||
若不可行,请查看 node 官网历代大版本的 lts 版本(长期维护),自行安装,查看是否能正常渲染,选取稳定渲染悦码的那一个 node 版本作为开发环境
|
||||
|
||||
## 5. 接入方式
|
||||
|
||||
### vue2 项目接入
|
||||
|
||||
```bash
|
||||
pnpm i @sy/wujie-vue2-renderer-adapter@latest --save
|
||||
# or 或者
|
||||
npm i @sy/wujie-vue2-renderer-adapter@latest --save
|
||||
```
|
||||
|
||||
### vue3 项目接入
|
||||
|
||||
```bash
|
||||
pnpm i @sy/wujie-vue3-renderer-adapter@latest --save
|
||||
# or 或者
|
||||
npm i @sy/wujie-vue3-renderer-adapter@latest --save
|
||||
```
|
||||
|
||||
### react 项目接入
|
||||
|
||||
```bash
|
||||
pnpm i @sy/wujie-react-renderer-adapter@latest --save
|
||||
# or 或者
|
||||
npm i @sy/wujie-react-renderer-adapter@latest --save
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
- 6.1 Props 参数详解
|
||||
- 6.2 事件监听与回调
|
||||
- 6.3 实例方法
|
||||
- 6.4 拦截器使用
|
||||
|
||||
## 7. 高级用法
|
||||
|
||||
- 7.1 自定义主题
|
||||
- 7.2 数据交互与通信
|
||||
- 7.3 插件扩展
|
||||
- 7.4 微前端降级处理
|
||||
|
||||
## 8. 故障排除
|
||||
|
||||
- 8.1 常见错误及解决方案
|
||||
- 8.2 日志与调试
|
||||
- 悦码的日志输出一般在控制台中有 `console.ts 40` 的源码位置标记
|
||||
- 8.3 兼容性问题处理
|
||||
- renderer-adapter 是默认使用无界降级的 iframe 加载悦码渲染器应用的,你如果希望悦码与你的页面有更深的上下文结合和交互,你可以手动设置 `degrade` 为 `false`,这将开启高级渲染,但有一定的兼容性问题,如果需要在 C 端运行业务,我建议你采用默认的渲染模式
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { WujieVue3RendererAdapter } from '@sy/wujie-vue3-renderer-adapter';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 高级渲染模式,与原页面深度共享 document 与内存上下文 -->
|
||||
<WujieVue3RendererAdapter
|
||||
:degrade="false"
|
||||
fileId="test123"
|
||||
projectId="test123"
|
||||
/>
|
||||
<!-- 默认降级渲染模式,使用无界 iframe 加载悦码渲染器应用 -->
|
||||
<!-- 缺点在于弹窗与遮罩层会约束在 iframe 空间内,无法与原页面共享 document,但无界的 iframe 可以与原页面共享内存上下文 ,这是比传统 iframe 更优的解决方案 -->
|
||||
<WujieVue3RendererAdapter fileId="test123" projectId="test123" />
|
||||
</template>
|
||||
```
|
||||
|
||||
- 8.4 性能问题诊断
|
||||
- 悦码渲染器内部使用了 sentry 上报错误,你可以跟 徐川(sy0182) 申请对应警告邮箱的使用权,获取报错邮件
|
||||
|
||||

|
||||
|
||||
## 9. 最佳实践
|
||||
|
||||
- 9.1 推荐的项目结构
|
||||
- 9.2 安全性建议
|
||||
- 9.3 性能优化建议
|
||||
- 9.4 版本升级策略
|
||||
|
||||
## 10. 示例
|
||||
|
||||
- 10.1 基础示例
|
||||
- 10.2 完整应用示例
|
||||
- 10.3 实际案例展示
|
||||
|
||||
## 11. 常见问题 (FAQ)
|
||||
|
||||
## 12. 联系支持与反馈渠道
|
@ -17,6 +17,15 @@ const app = createApp(App);
|
||||
Sentry.init({
|
||||
app,
|
||||
dsn: 'https://5bcf1344794fea64fc5e5fe7da4821c1@o4508962650783744.ingest.de.sentry.io/4508962653143120',
|
||||
integrations: [
|
||||
// 异常路径回放
|
||||
Sentry.replayIntegration(),
|
||||
// 异常端信息追踪
|
||||
Sentry.browserTracingIntegration(),
|
||||
],
|
||||
// Session Replay
|
||||
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
|
||||
replaysOnErrorSampleRate: 1, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
|
||||
});
|
||||
|
||||
// 批量注册组件
|
||||
|
3
apps/renderer/src/utils/alert.ts
Normal file
3
apps/renderer/src/utils/alert.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function test() {
|
||||
console.log('test');
|
||||
}
|
1
apps/renderer/src/utils/index.ts
Normal file
1
apps/renderer/src/utils/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './alert';
|
39
packages/renderer-adapter/wujie-vue2/package.json
Normal file
39
packages/renderer-adapter/wujie-vue2/package.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@sy/wujie-vue3-renderer-adapter",
|
||||
"version": "1.0.0-alpha.2",
|
||||
"description": "wujie-vue3 ycode renderer adapter",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"alias": {
|
||||
"#": "./src"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"unpkg": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs",
|
||||
"default": "./dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"licia-es": "catalog:",
|
||||
"vue": "2.7.16",
|
||||
"wujie-vue2": "1.0.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/axios": "0.14.4",
|
||||
"@vitejs/plugin-vue": "catalog:",
|
||||
"axios": "catalog:",
|
||||
"vite-plugin-dts": "catalog:",
|
||||
"vue-router": ""
|
||||
}
|
||||
}
|
132
packages/renderer-adapter/wujie-vue2/src/adapter.vue
Normal file
132
packages/renderer-adapter/wujie-vue2/src/adapter.vue
Normal file
@ -0,0 +1,132 @@
|
||||
<script setup lang="ts">
|
||||
import type { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||
|
||||
import type { Router, RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
|
||||
import WujieVue from 'wujie-vue3';
|
||||
|
||||
// @ts-ignore ignore the type error
|
||||
import { version } from '/package.json';
|
||||
|
||||
// 定义拦截器类型
|
||||
interface AxiosInterceptors {
|
||||
request?: {
|
||||
onFulfilled?: (
|
||||
config: InternalAxiosRequestConfig,
|
||||
) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
|
||||
onRejected?: (error: any) => any;
|
||||
};
|
||||
response?: {
|
||||
onFulfilled?: (
|
||||
response: AxiosResponse,
|
||||
) => AxiosResponse | Promise<AxiosResponse>;
|
||||
onRejected?: (error: any) => any;
|
||||
};
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
[key: string]: any;
|
||||
applicationId: number;
|
||||
degrade?: boolean;
|
||||
fileId: number | string;
|
||||
interceptors?: AxiosInterceptors;
|
||||
name?: string;
|
||||
// 传递给子应用的参数 payload
|
||||
payload?: Record<string, any>;
|
||||
projectId: number;
|
||||
route?: RouteRecordRaw;
|
||||
router?: Router;
|
||||
sync?: boolean;
|
||||
url?: string;
|
||||
}>(),
|
||||
{
|
||||
// 默认 wujie 降级,能避免很多兼容问题
|
||||
degrade: true,
|
||||
// 默认不使用拦截器
|
||||
interceptors: () => ({}),
|
||||
// 默认不使用 name
|
||||
name: undefined,
|
||||
// 默认不使用 payload
|
||||
payload: () => ({}),
|
||||
// 默认不使用 route
|
||||
route: undefined,
|
||||
// 默认不使用 router
|
||||
router: undefined,
|
||||
sync: true,
|
||||
url: 'https://y-code-renderer.shiyue.com',
|
||||
},
|
||||
);
|
||||
|
||||
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(`${props.name} 收到子应用消息:`, data);
|
||||
};
|
||||
|
||||
// 准备传递给子应用的数据
|
||||
const subAppProps = {
|
||||
...props,
|
||||
adapterInfo: {
|
||||
version,
|
||||
},
|
||||
};
|
||||
|
||||
// 监听子应用的事件
|
||||
const handleReady = (data: any) => {
|
||||
console.log(`${props.name} 子应用就绪:`, data);
|
||||
// 可以在这里执行一些操作
|
||||
};
|
||||
|
||||
const handleRenderSuccess = () => {
|
||||
console.log(`${props.name} 子应用渲染成功`);
|
||||
// 通知父应用
|
||||
};
|
||||
|
||||
const handleRenderFail = (error: any) => {
|
||||
console.error(`${props.name} 子应用渲染失败:`, 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>
|
||||
<WujieVue
|
||||
:name="name || fileId"
|
||||
:url="url"
|
||||
:sync="sync"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:degrade="degrade"
|
||||
:props="subAppProps"
|
||||
:before-load="beforeLoad"
|
||||
:after-mount="afterMount"
|
||||
/>
|
||||
</template>
|
1
packages/renderer-adapter/wujie-vue2/src/index.ts
Normal file
1
packages/renderer-adapter/wujie-vue2/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './adapter.vue';
|
29
packages/renderer-adapter/wujie-vue2/tsconfig.json
Normal file
29
packages/renderer-adapter/wujie-vue2/tsconfig.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"jsx": "preserve",
|
||||
"jsxFactory": "h",
|
||||
"jsxFragmentFactory": "Fragment",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"baseUrl": ".",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"types": ["vite/client", "vue/runtime-dom"],
|
||||
"strict": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"declaration": true,
|
||||
"declarationDir": "dist/types",
|
||||
"outDir": "dist",
|
||||
"sourceMap": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
68
packages/renderer-adapter/wujie-vue2/vite.config.ts
Normal file
68
packages/renderer-adapter/wujie-vue2/vite.config.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { defineConfig } from 'vite';
|
||||
import dts from 'vite-plugin-dts';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
cssCodeSplit: true,
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, 'src/index.ts'),
|
||||
fileName: (format) => {
|
||||
switch (format) {
|
||||
case 'cjs': {
|
||||
return 'index.cjs';
|
||||
}
|
||||
case 'es': {
|
||||
return 'index.mjs';
|
||||
}
|
||||
case 'umd': {
|
||||
return 'index.js';
|
||||
}
|
||||
default: {
|
||||
return `index.${format}.js`;
|
||||
}
|
||||
}
|
||||
},
|
||||
formats: ['es', 'cjs', 'umd'],
|
||||
name: 'RendererAdapter',
|
||||
},
|
||||
outDir: 'dist',
|
||||
rollupOptions: {
|
||||
external: ['vue'],
|
||||
output: {
|
||||
assetFileNames: (assetInfo) => {
|
||||
if (assetInfo.name === 'style.css') return 'assets/[name][extname]';
|
||||
return 'assets/[name]-[hash][extname]';
|
||||
},
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
},
|
||||
},
|
||||
},
|
||||
sourcemap: true,
|
||||
},
|
||||
css: {
|
||||
extract: false,
|
||||
modules: {
|
||||
localsConvention: 'camelCaseOnly',
|
||||
scopeBehaviour: 'local',
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue({
|
||||
css: {
|
||||
injectCss: true,
|
||||
},
|
||||
}),
|
||||
dts({
|
||||
insertTypesEntry: true,
|
||||
outDir: 'dist/types',
|
||||
staticImport: true,
|
||||
}),
|
||||
],
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user