69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
import { useState, useCallback, useEffect } from 'react';
|
||
import dynamic from 'next/dynamic';
|
||
|
||
export interface WidgetModule {
|
||
id: string;
|
||
name: string;
|
||
version: string;
|
||
component: ReturnType<typeof dynamic>;
|
||
}
|
||
|
||
export const useDynamicWidgets = (): {
|
||
widgets: WidgetModule[];
|
||
refreshWidgets: () => Promise<void>;
|
||
} => {
|
||
const [widgets, setWidgets] = useState<WidgetModule[]>([]);
|
||
|
||
const loadWidgets = useCallback(async () => {
|
||
try {
|
||
// Webpack 的 require.context 匹配 widgets 目录
|
||
const context = require.context('../widgets', true, /\/index\.tsx$/);
|
||
console.log("[DEBUG] Matched files:", context.keys());
|
||
|
||
|
||
|
||
const modules = await Promise.all(
|
||
context.keys().map(async (key) => {
|
||
const folderName = key.split('/')[1];
|
||
|
||
// 动态导入元数据
|
||
console.log("[DEBUG] import files:", `../widgets/${folderName}/index.tsx`);
|
||
|
||
const meta = await import(`../widgets/${folderName}/index.tsx`);
|
||
|
||
// 创建动态组件(单独导入确保 Tree Shaking)
|
||
const Component = dynamic(
|
||
() => import(`../widgets/${folderName}/index.tsx`),
|
||
{ ssr: false }
|
||
);
|
||
|
||
return {
|
||
id: meta.id,
|
||
name: meta.name,
|
||
version: meta.version,
|
||
component: Component
|
||
};
|
||
})
|
||
);
|
||
console.log(modules);
|
||
|
||
setWidgets(modules);
|
||
} catch (error) {
|
||
console.error('Failed to load widgets:', error);
|
||
setWidgets([]);
|
||
}
|
||
}, []);
|
||
|
||
// 初始化加载
|
||
useEffect(() => {
|
||
loadWidgets();
|
||
}, [loadWidgets]);
|
||
|
||
// 暴露刷新方法
|
||
const refreshWidgets = useCallback(async () => {
|
||
await loadWidgets();
|
||
}, [loadWidgets]);
|
||
|
||
return { widgets, refreshWidgets };
|
||
};
|