perf: 优化管理端生产加载体验
- 图标与重型组件按需加载,优化菜单预取和页面请求链路 - 开启 gzip 与静态缓存并修复子路由 KeepAlive 冲突
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import type { RouteRecordStringComponent } from '@easyflow/types';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { disableUnsafeMenuRouteCaching } from '../route-cache-safety';
|
||||
|
||||
function createRoute(
|
||||
path: string,
|
||||
children?: RouteRecordStringComponent[],
|
||||
): RouteRecordStringComponent {
|
||||
return {
|
||||
children,
|
||||
component: '/example/Index',
|
||||
meta: { keepAlive: true, title: path },
|
||||
name: path,
|
||||
path,
|
||||
};
|
||||
}
|
||||
|
||||
describe('route cache safety', () => {
|
||||
it('disables stale keep-alive metadata for affected menus recursively', () => {
|
||||
const knowledgeRoute = createRoute('/ai/documentCollection');
|
||||
const routes = [
|
||||
createRoute('/ai/workflow'),
|
||||
createRoute('/ai', [knowledgeRoute]),
|
||||
];
|
||||
|
||||
expect(disableUnsafeMenuRouteCaching(routes)).toBe(routes);
|
||||
expect(routes[0]?.meta?.keepAlive).toBe(false);
|
||||
expect(knowledgeRoute.meta?.keepAlive).toBe(false);
|
||||
});
|
||||
|
||||
it('does not change unrelated route caching', () => {
|
||||
const unrelatedRoute = createRoute('/example/cached');
|
||||
|
||||
disableUnsafeMenuRouteCaching([unrelatedRoute]);
|
||||
|
||||
expect(unrelatedRoute.meta?.keepAlive).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
} from '@easyflow/types';
|
||||
|
||||
import { generateAccessible } from '@easyflow/access';
|
||||
import { loadMissingIconCollections } from '@easyflow/icons';
|
||||
import { preferences } from '@easyflow/preferences';
|
||||
|
||||
import { ElMessage } from 'element-plus';
|
||||
@@ -12,8 +13,35 @@ import { getAllMenusApi } from '#/api';
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { disableUnsafeMenuRouteCaching } from './route-cache-safety';
|
||||
|
||||
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
|
||||
|
||||
function collectMenuIcons(routes: unknown[]): string[] {
|
||||
const icons: string[] = [];
|
||||
routes.forEach((item) => {
|
||||
if (!item || typeof item !== 'object') {
|
||||
return;
|
||||
}
|
||||
const route = item as Record<string, unknown>;
|
||||
const meta =
|
||||
route.meta && typeof route.meta === 'object'
|
||||
? (route.meta as Record<string, unknown>)
|
||||
: undefined;
|
||||
[route.icon, route.activeIcon, meta?.icon, meta?.activeIcon].forEach(
|
||||
(icon) => {
|
||||
if (typeof icon === 'string') {
|
||||
icons.push(icon);
|
||||
}
|
||||
},
|
||||
);
|
||||
if (Array.isArray(route.children)) {
|
||||
icons.push(...collectMenuIcons(route.children));
|
||||
}
|
||||
});
|
||||
return icons;
|
||||
}
|
||||
|
||||
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
||||
const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
@@ -29,7 +57,9 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
||||
duration: 1500,
|
||||
message: `${$t('common.loadingMenu')}...`,
|
||||
});
|
||||
return await getAllMenusApi();
|
||||
const menuRoutes = await getAllMenusApi();
|
||||
await loadMissingIconCollections(collectMenuIcons(menuRoutes));
|
||||
return disableUnsafeMenuRouteCaching(menuRoutes);
|
||||
},
|
||||
// 可以指定没有权限跳转403页面
|
||||
forbiddenComponent,
|
||||
|
||||
31
easyflow-ui-admin/app/src/router/route-cache-safety.ts
Normal file
31
easyflow-ui-admin/app/src/router/route-cache-safety.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { RouteRecordStringComponent } from '@easyflow/types';
|
||||
|
||||
const UNSAFE_KEEP_ALIVE_MENU_PATHS = new Set([
|
||||
'/ai/agents',
|
||||
'/ai/documentCollection',
|
||||
'/ai/model',
|
||||
'/ai/skill',
|
||||
'/ai/workflow',
|
||||
'/dashboard/workspace',
|
||||
'/sys/sysAccount',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Disable route-level caching that conflicts with independent hidden child
|
||||
* routes. Assigning false also replaces stale true values in persisted tabs.
|
||||
*/
|
||||
function disableUnsafeMenuRouteCaching(
|
||||
routes: RouteRecordStringComponent[],
|
||||
): RouteRecordStringComponent[] {
|
||||
for (const route of routes) {
|
||||
if (UNSAFE_KEEP_ALIVE_MENU_PATHS.has(route.path) && route.meta) {
|
||||
route.meta.keepAlive = false;
|
||||
}
|
||||
if (route.children?.length) {
|
||||
disableUnsafeMenuRouteCaching(route.children);
|
||||
}
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
|
||||
export { disableUnsafeMenuRouteCaching };
|
||||
Reference in New Issue
Block a user