import type { AsyncComponentLoader, Component } from 'vue' import { defineAsyncComponent } from 'vue' /** * 安全的异步组件加载器 * 防止在组件卸载时继续加载导致的内存泄漏和错误 */ export function safeAsyncComponent( loader: AsyncComponentLoader, options?: { loadingComponent?: Component errorComponent?: Component delay?: number timeout?: number suspensible?: boolean onError?: (error: Error, retry: () => void, fail: () => void, attempts: number) => any }, ) { const safeLoader: AsyncComponentLoader = () => { return loader().catch((error) => { console.error('异步组件加载失败:', error) // 如果是网络错误或者加载错误,返回一个空的组件 if (error.name === 'ChunkLoadError' || error.message?.includes('Loading chunk')) { console.warn('检测到代码分割加载错误,尝试重新加载页面') // 延迟重新加载页面,避免无限循环 setTimeout(() => { window.location.reload() }, 1000) } // 返回一个错误组件 return Promise.resolve({ template: '
组件加载失败
', }) }) } return defineAsyncComponent({ loader: safeLoader, loadingComponent: options?.loadingComponent, errorComponent: options?.errorComponent, delay: options?.delay ?? 200, timeout: options?.timeout ?? 30000, suspensible: options?.suspensible ?? false, onError: options?.onError || ((error, retry, fail, attempts) => { console.error(`异步组件加载错误 (第${attempts}次尝试):`, error) if (attempts <= 3) { retry() } else { fail() } }), }) } /** * 创建路由组件的安全加载器 */ export function createSafeRouteComponent(componentPath: string) { return safeAsyncComponent( () => import(/* @vite-ignore */ `/src/views${componentPath}.vue`), { delay: 100, timeout: 10000, onError: (error, retry, fail, attempts) => { console.error(`路由组件加载失败: ${componentPath}`, error) // 对于路由组件,最多重试2次 if (attempts <= 2) { console.warn(`重试加载组件: ${componentPath} (第${attempts}次)`) retry() } else { console.error(`组件加载最终失败: ${componentPath}`) fail() } }, }, ) } /** * 清理组件缓存,用于解决热更新时的问题 */ export function clearComponentCache() { // 在开发环境下清理模块缓存 if (import.meta.hot) { import.meta.hot.invalidate() } } /** * 组件安全性检查 */ export function validateComponent(component: any): boolean { if (!component) { console.error('组件为空或未定义') return false } if (typeof component !== 'object' && typeof component !== 'function') { console.error('组件类型不正确:', typeof component) return false } return true }