@vlian/framework 1.2.59 → 1.2.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/index.cjs +1 -22
- package/dist/analytics.umd.js +1 -1
- package/dist/components/LocaleSwitch.cjs +1 -116
- package/dist/components/ThemeSwitch.cjs +1 -115
- package/dist/components/index.cjs +1 -20
- package/dist/components/persistence.cjs +1 -58
- package/dist/core/Test.cjs +1 -64
- package/dist/core/app/AppContext.cjs +1 -348
- package/dist/core/app/AppContext.types.cjs +1 -4
- package/dist/core/app/BasicLayout.cjs +1 -122
- package/dist/core/app/DefaultApp.cjs +1 -150
- package/dist/core/app/index.cjs +1 -41
- package/dist/core/config/AppConfig.cjs +1 -139
- package/dist/core/config/ConfigLoader.cjs +1 -323
- package/dist/core/config/ConfigValidator.cjs +2 -133
- package/dist/core/config/index.cjs +1 -28
- package/dist/core/dev/DevTools.cjs +1 -226
- package/dist/core/error/ErrorBoundary.cjs +1 -401
- package/dist/core/error/ErrorHandler.cjs +1 -275
- package/dist/core/error/index.cjs +1 -34
- package/dist/core/event/AppEventBus.cjs +1 -444
- package/dist/core/event/frameworkEvents.cjs +1 -141
- package/dist/core/event/hooks.cjs +1 -69
- package/dist/core/event/index.cjs +1 -41
- package/dist/core/event/types.cjs +1 -62
- package/dist/core/event/useEventBus.cjs +1 -25
- package/dist/core/index.cjs +1 -140
- package/dist/core/initialization/InitializationErrorThrower.cjs +1 -75
- package/dist/core/initialization/index.cjs +1 -26
- package/dist/core/initialization/initialization.cjs +1 -64
- package/dist/core/initialization/initializationErrorState.cjs +1 -66
- package/dist/core/kernel/defaultAdapters.cjs +1 -184
- package/dist/core/kernel/errors.cjs +1 -69
- package/dist/core/kernel/index.cjs +1 -20
- package/dist/core/kernel/startKernel.cjs +1 -200
- package/dist/core/kernel/types.cjs +1 -4
- package/dist/core/middleware.cjs +1 -73
- package/dist/core/plugin/PluginEventBus.cjs +1 -298
- package/dist/core/plugin/PluginSandbox.cjs +1 -137
- package/dist/core/plugin.cjs +1 -494
- package/dist/core/router/RouterManager.cjs +1 -286
- package/dist/core/router/adapter/AdapterManager.cjs +1 -235
- package/dist/core/router/adapter/index.cjs +1 -22
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs +1 -128
- package/dist/core/router/adapter/react-router/index.cjs +1 -20
- package/dist/core/router/adapter/types.cjs +1 -6
- package/dist/core/router/dev/RouterDevTools.cjs +1 -260
- package/dist/core/router/dev/index.cjs +1 -20
- package/dist/core/router/dynamic/DynamicRouteManager.cjs +1 -193
- package/dist/core/router/dynamic/index.cjs +1 -20
- package/dist/core/router/errors/RouterError.cjs +1 -61
- package/dist/core/router/errors/index.cjs +1 -20
- package/dist/core/router/index.cjs +1 -36
- package/dist/core/router/lifecycle/RouterLifecycleManager.cjs +1 -144
- package/dist/core/router/lifecycle/index.cjs +1 -20
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs +1 -193
- package/dist/core/router/middleware/auth.cjs +1 -66
- package/dist/core/router/middleware/index.cjs +1 -22
- package/dist/core/router/middleware/types.cjs +1 -6
- package/dist/core/router/monitoring/RouterMonitoring.cjs +1 -227
- package/dist/core/router/monitoring/index.cjs +1 -20
- package/dist/core/router/navigation/RouterNavigation.cjs +1 -239
- package/dist/core/router/navigation/index.cjs +1 -20
- package/dist/core/router/performance/RouteCache.cjs +1 -305
- package/dist/core/router/performance/RoutePreloader.cjs +1 -292
- package/dist/core/router/performance/index.cjs +1 -21
- package/dist/core/router/plugin/RouterPluginManager.cjs +1 -262
- package/dist/core/router/plugin/index.cjs +1 -21
- package/dist/core/router/plugin/types.cjs +1 -39
- package/dist/core/router/types.cjs +1 -4
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.cjs +1 -129
- package/dist/core/router/utils/adapters/react-router/transform.cjs +1 -250
- package/dist/core/router/utils/transform.cjs +1 -780
- package/dist/core/router/validation/RouterConfigValidator.cjs +2 -83
- package/dist/core/router/validation/index.cjs +1 -21
- package/dist/core/router/validation/schema.cjs +1 -159
- package/dist/core/router/version/RouteVersionManager.cjs +1 -205
- package/dist/core/router/version/index.cjs +1 -20
- package/dist/core/splash/SplashScreen.cjs +1 -341
- package/dist/core/splash/index.cjs +1 -22
- package/dist/core/splash/splashScreenUtils.cjs +1 -38
- package/dist/core/startup/AppInstance.cjs +1 -239
- package/dist/core/startup/environment.cjs +1 -169
- package/dist/core/startup/index.cjs +1 -23
- package/dist/core/startup/initializeServices.cjs +1 -226
- package/dist/core/startup/performanceTracker.cjs +1 -179
- package/dist/core/startup/renderApp.cjs +1 -314
- package/dist/core/startup/startApp.cjs +1 -317
- package/dist/core/types.cjs +1 -4
- package/dist/index.cjs +1 -52
- package/dist/index.umd.cjs +1 -27
- package/dist/index.umd.js +1 -1
- package/dist/kernel/constants.cjs +1 -65
- package/dist/kernel/index.cjs +1 -38
- package/dist/kernel/kernel.cjs +1 -295
- package/dist/kernel/manager/cacheManager.cjs +1 -46
- package/dist/kernel/manager/i18n/I18nManager.cjs +1 -91
- package/dist/kernel/manager/i18n/i18n.persistence.cjs +1 -60
- package/dist/kernel/manager/i18n/i18n.schema.cjs +1 -86
- package/dist/kernel/manager/i18n/index.cjs +1 -11
- package/dist/kernel/manager/i18nManager.cjs +1 -11
- package/dist/kernel/manager/index.cjs +1 -28
- package/dist/kernel/manager/logger/LoggerManager.cjs +1 -107
- package/dist/kernel/manager/logger/index.cjs +1 -11
- package/dist/kernel/manager/logger/logger.persistence.cjs +1 -62
- package/dist/kernel/manager/logger/logger.schema.cjs +1 -74
- package/dist/kernel/manager/loggerManager.cjs +1 -11
- package/dist/kernel/manager/theme/ThemeManager.cjs +1 -84
- package/dist/kernel/manager/theme/index.cjs +1 -11
- package/dist/kernel/manager/theme/theme.dom.cjs +1 -61
- package/dist/kernel/manager/theme/theme.persistence.cjs +1 -57
- package/dist/kernel/manager/theme/theme.schema.cjs +1 -122
- package/dist/kernel/manager/themeManager.cjs +1 -11
- package/dist/kernel/types.cjs +1 -4
- package/dist/library/index.cjs +1 -19
- package/dist/library/locale/index.cjs +1 -39
- package/dist/library/locale/langs/en-us/index.cjs +1 -32
- package/dist/library/locale/langs/zh-cn/index.cjs +1 -32
- package/dist/library/locale/types.cjs +1 -4
- package/dist/library/storage/cache.cjs +1 -243
- package/dist/library/storage/encryption.cjs +1 -147
- package/dist/library/storage/index.cjs +1 -124
- package/dist/state/StateManager.cjs +1 -166
- package/dist/state/adapters/AdapterFactory.cjs +1 -89
- package/dist/state/adapters/DefaultAdapter.cjs +1 -75
- package/dist/state/adapters/ReduxAdapter.cjs +1 -443
- package/dist/state/adapters/ZustandAdapter.cjs +1 -69
- package/dist/state/adapters/index.cjs +1 -44
- package/dist/state/adapters/types.cjs +1 -20
- package/dist/state/core/DerivedStateInstance.cjs +1 -174
- package/dist/state/core/StateInstance.cjs +1 -170
- package/dist/state/core/StateRegistry.cjs +1 -110
- package/dist/state/core/StateScope.cjs +1 -137
- package/dist/state/core/index.cjs +1 -30
- package/dist/state/index.cjs +1 -30
- package/dist/state/types.cjs +1 -12
- package/dist/state.umd.js +1 -1
- package/dist/types.cjs +1 -4
- package/dist/utils/analytics.cjs +1 -217
- package/dist/utils/configSecurity.cjs +3 -182
- package/dist/utils/csrf.cjs +1 -18
- package/dist/utils/errors/ErrorCodes.cjs +1 -25
- package/dist/utils/errors.cjs +1 -111
- package/dist/utils/index.cjs +1 -135
- package/dist/utils/logger.cjs +1 -25
- package/dist/utils/logger.types.cjs +1 -11
- package/dist/utils/monitoring.cjs +1 -18
- package/dist/utils/performance.cjs +1 -22
- package/dist/utils/resourceLoader.cjs +1 -22
- package/dist/utils/runtimeSecurity.cjs +1 -11
- package/dist/utils/security.cjs +1 -19
- package/dist/utils/traceId.cjs +1 -37
- package/dist/utils/validation.cjs +1 -19
- package/package.json +7 -3
|
@@ -1,305 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 路由缓存管理器
|
|
3
|
-
* 提供路由转换结果、匹配结果的缓存功能
|
|
4
|
-
*/ "use strict";
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
function _export(target, all) {
|
|
9
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
_export(exports, {
|
|
15
|
-
get RouteCache () {
|
|
16
|
-
return RouteCache;
|
|
17
|
-
},
|
|
18
|
-
get getRouteCache () {
|
|
19
|
-
return getRouteCache;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
const _logger = require("@vlian/logger");
|
|
23
|
-
function _define_property(obj, key, value) {
|
|
24
|
-
if (key in obj) {
|
|
25
|
-
Object.defineProperty(obj, key, {
|
|
26
|
-
value: value,
|
|
27
|
-
enumerable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
writable: true
|
|
30
|
-
});
|
|
31
|
-
} else {
|
|
32
|
-
obj[key] = value;
|
|
33
|
-
}
|
|
34
|
-
return obj;
|
|
35
|
-
}
|
|
36
|
-
let RouteCache = class RouteCache {
|
|
37
|
-
/**
|
|
38
|
-
* 初始化持久化缓存
|
|
39
|
-
*/ async initPersistence() {
|
|
40
|
-
try {
|
|
41
|
-
// 检查 IndexedDB 是否可用
|
|
42
|
-
if (typeof window !== 'undefined' && 'indexedDB' in window) {
|
|
43
|
-
this.persistenceEnabled = true;
|
|
44
|
-
await this.loadFromPersistence();
|
|
45
|
-
_logger.logger.debug('路由缓存持久化已启用');
|
|
46
|
-
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
_logger.logger.warn('路由缓存持久化初始化失败', error);
|
|
49
|
-
this.persistenceEnabled = false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* 从持久化存储加载缓存
|
|
54
|
-
*/ async loadFromPersistence() {
|
|
55
|
-
try {
|
|
56
|
-
// 这里可以实现从 IndexedDB 加载缓存的逻辑
|
|
57
|
-
// 由于 IndexedDB 操作较复杂,这里先留空
|
|
58
|
-
// 实际实现可以使用 idb 库或原生 IndexedDB API
|
|
59
|
-
} catch (error) {
|
|
60
|
-
_logger.logger.warn('从持久化存储加载缓存失败', error);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 保存到持久化存储
|
|
65
|
-
*/ async saveToPersistence(_key, _value) {
|
|
66
|
-
if (!this.persistenceEnabled) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
// 这里可以实现保存到 IndexedDB 的逻辑
|
|
71
|
-
// 实际实现可以使用 idb 库或原生 IndexedDB API
|
|
72
|
-
} catch (error) {
|
|
73
|
-
_logger.logger.warn('保存到持久化存储失败', error);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* 生成缓存键
|
|
78
|
-
*/ generateKey(routes) {
|
|
79
|
-
if (typeof routes === 'function') {
|
|
80
|
-
// 对于函数,使用函数名或随机 ID
|
|
81
|
-
return `fn_${routes.name || Math.random().toString(36).substring(7)}`;
|
|
82
|
-
}
|
|
83
|
-
// 对于数组,使用 JSON.stringify 生成键(注意:这可能会很慢)
|
|
84
|
-
// 实际使用中可以考虑使用路由配置的哈希值
|
|
85
|
-
try {
|
|
86
|
-
const routesStr = JSON.stringify(routes, (_key, value)=>{
|
|
87
|
-
// 过滤掉函数,避免序列化问题
|
|
88
|
-
if (typeof value === 'function') {
|
|
89
|
-
return '[Function]';
|
|
90
|
-
}
|
|
91
|
-
return value;
|
|
92
|
-
});
|
|
93
|
-
return `routes_${this.hashString(routesStr)}`;
|
|
94
|
-
} catch (error) {
|
|
95
|
-
// 如果序列化失败,使用随机键
|
|
96
|
-
return `routes_${Math.random().toString(36).substring(7)}`;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* 字符串哈希函数(简单实现)
|
|
101
|
-
*/ hashString(str) {
|
|
102
|
-
let hash = 0;
|
|
103
|
-
for(let i = 0; i < str.length; i++){
|
|
104
|
-
const char = str.charCodeAt(i);
|
|
105
|
-
hash = (hash << 5) - hash + char;
|
|
106
|
-
hash = hash & hash; // 转换为 32 位整数
|
|
107
|
-
}
|
|
108
|
-
return Math.abs(hash).toString(36);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* 检查缓存项是否过期
|
|
112
|
-
*/ isExpired(item) {
|
|
113
|
-
return Date.now() > item.expiresAt;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* 清理过期缓存
|
|
117
|
-
*/ cleanup() {
|
|
118
|
-
// 清理转换结果缓存
|
|
119
|
-
for (const [key, item] of this.cache.entries()){
|
|
120
|
-
if (this.isExpired(item)) {
|
|
121
|
-
this.cache.delete(key);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// 清理匹配结果缓存
|
|
125
|
-
for (const [key, item] of this.matchCache.entries()){
|
|
126
|
-
if (this.isExpired(item)) {
|
|
127
|
-
this.matchCache.delete(key);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// 如果缓存超过最大大小,删除最久未访问的项(LRU)
|
|
131
|
-
this.evictLRU();
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* LRU 淘汰策略
|
|
135
|
-
*/ evictLRU() {
|
|
136
|
-
// 清理转换结果缓存
|
|
137
|
-
if (this.cache.size > this.config.maxSize) {
|
|
138
|
-
const sorted = Array.from(this.cache.entries()).sort((a, b)=>a[1].lastAccessedAt - b[1].lastAccessedAt);
|
|
139
|
-
const toDelete = sorted.slice(0, this.cache.size - this.config.maxSize);
|
|
140
|
-
toDelete.forEach(([key])=>this.cache.delete(key));
|
|
141
|
-
}
|
|
142
|
-
// 清理匹配结果缓存
|
|
143
|
-
if (this.matchCache.size > this.config.maxSize) {
|
|
144
|
-
const sorted = Array.from(this.matchCache.entries()).sort((a, b)=>a[1].lastAccessedAt - b[1].lastAccessedAt);
|
|
145
|
-
const toDelete = sorted.slice(0, this.matchCache.size - this.config.maxSize);
|
|
146
|
-
toDelete.forEach(([key])=>this.matchCache.delete(key));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* 启动定期清理
|
|
151
|
-
*/ startCleanupInterval() {
|
|
152
|
-
if (this.cleanupTimer) {
|
|
153
|
-
clearInterval(this.cleanupTimer);
|
|
154
|
-
}
|
|
155
|
-
// 每 1 分钟清理一次过期缓存
|
|
156
|
-
this.cleanupTimer = setInterval(()=>{
|
|
157
|
-
this.cleanup();
|
|
158
|
-
}, 60 * 1000);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* 获取转换结果缓存
|
|
162
|
-
*/ get(routes) {
|
|
163
|
-
const key = this.generateKey(routes);
|
|
164
|
-
const item = this.cache.get(key);
|
|
165
|
-
if (!item) {
|
|
166
|
-
this.stats.transformMisses++;
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
if (this.isExpired(item)) {
|
|
170
|
-
this.cache.delete(key);
|
|
171
|
-
this.stats.transformMisses++;
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
// 更新访问信息
|
|
175
|
-
item.lastAccessedAt = Date.now();
|
|
176
|
-
item.accessCount++;
|
|
177
|
-
this.stats.transformHits++;
|
|
178
|
-
return item.value;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* 设置转换结果缓存
|
|
182
|
-
*/ set(routes, value) {
|
|
183
|
-
const key = this.generateKey(routes);
|
|
184
|
-
const now = Date.now();
|
|
185
|
-
const item = {
|
|
186
|
-
value,
|
|
187
|
-
expiresAt: now + this.config.ttl,
|
|
188
|
-
createdAt: now,
|
|
189
|
-
accessCount: 0,
|
|
190
|
-
lastAccessedAt: now
|
|
191
|
-
};
|
|
192
|
-
this.cache.set(key, item);
|
|
193
|
-
// 保存到持久化存储
|
|
194
|
-
if (this.persistenceEnabled) {
|
|
195
|
-
this.saveToPersistence(key, value).catch((error)=>{
|
|
196
|
-
_logger.logger.warn('保存缓存到持久化存储失败', error);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
// 检查是否需要淘汰
|
|
200
|
-
this.evictLRU();
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* 获取路由匹配缓存
|
|
204
|
-
*/ getMatch(path) {
|
|
205
|
-
const item = this.matchCache.get(path);
|
|
206
|
-
if (!item) {
|
|
207
|
-
this.stats.matchMisses++;
|
|
208
|
-
return undefined;
|
|
209
|
-
}
|
|
210
|
-
if (this.isExpired(item)) {
|
|
211
|
-
this.matchCache.delete(path);
|
|
212
|
-
this.stats.matchMisses++;
|
|
213
|
-
return undefined;
|
|
214
|
-
}
|
|
215
|
-
// 更新访问信息
|
|
216
|
-
item.lastAccessedAt = Date.now();
|
|
217
|
-
item.accessCount++;
|
|
218
|
-
this.stats.matchHits++;
|
|
219
|
-
return item.value;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* 设置路由匹配缓存
|
|
223
|
-
*/ setMatch(path, route) {
|
|
224
|
-
const now = Date.now();
|
|
225
|
-
const item = {
|
|
226
|
-
value: route,
|
|
227
|
-
expiresAt: now + this.config.ttl,
|
|
228
|
-
createdAt: now,
|
|
229
|
-
accessCount: 0,
|
|
230
|
-
lastAccessedAt: now
|
|
231
|
-
};
|
|
232
|
-
this.matchCache.set(path, item);
|
|
233
|
-
// 检查是否需要淘汰
|
|
234
|
-
this.evictLRU();
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* 清空所有缓存
|
|
238
|
-
*/ clear() {
|
|
239
|
-
this.cache.clear();
|
|
240
|
-
this.matchCache.clear();
|
|
241
|
-
this.stats = {
|
|
242
|
-
transformHits: 0,
|
|
243
|
-
transformMisses: 0,
|
|
244
|
-
matchHits: 0,
|
|
245
|
-
matchMisses: 0
|
|
246
|
-
};
|
|
247
|
-
_logger.logger.debug('路由缓存已清空');
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* 销毁缓存实例并释放资源
|
|
251
|
-
*/ destroy() {
|
|
252
|
-
this.clear();
|
|
253
|
-
if (this.cleanupTimer) {
|
|
254
|
-
clearInterval(this.cleanupTimer);
|
|
255
|
-
this.cleanupTimer = null;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* 获取缓存统计信息
|
|
260
|
-
*/ getStats() {
|
|
261
|
-
const totalHits = this.stats.transformHits + this.stats.matchHits;
|
|
262
|
-
const totalAccess = totalHits + this.stats.transformMisses + this.stats.matchMisses;
|
|
263
|
-
const hitRate = totalAccess > 0 ? totalHits / totalAccess : 0;
|
|
264
|
-
return {
|
|
265
|
-
transformCacheSize: this.cache.size,
|
|
266
|
-
matchCacheSize: this.matchCache.size,
|
|
267
|
-
totalSize: this.cache.size + this.matchCache.size,
|
|
268
|
-
hitRate
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
constructor(config = {}){
|
|
272
|
-
_define_property(this, "cache", new Map());
|
|
273
|
-
_define_property(this, "matchCache", new Map());
|
|
274
|
-
_define_property(this, "config", void 0);
|
|
275
|
-
_define_property(this, "persistenceEnabled", false);
|
|
276
|
-
_define_property(this, "cleanupTimer", null);
|
|
277
|
-
_define_property(this, "stats", {
|
|
278
|
-
transformHits: 0,
|
|
279
|
-
transformMisses: 0,
|
|
280
|
-
matchHits: 0,
|
|
281
|
-
matchMisses: 0
|
|
282
|
-
});
|
|
283
|
-
this.config = {
|
|
284
|
-
maxSize: config.maxSize ?? 50,
|
|
285
|
-
ttl: config.ttl ?? 5 * 60 * 1000,
|
|
286
|
-
enablePersistence: config.enablePersistence ?? false,
|
|
287
|
-
persistenceKeyPrefix: config.persistenceKeyPrefix ?? 'router_cache_'
|
|
288
|
-
};
|
|
289
|
-
// 初始化持久化缓存
|
|
290
|
-
if (this.config.enablePersistence && typeof window !== 'undefined' && 'indexedDB' in window) {
|
|
291
|
-
this.initPersistence();
|
|
292
|
-
}
|
|
293
|
-
// 定期清理过期缓存
|
|
294
|
-
this.startCleanupInterval();
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
/**
|
|
298
|
-
* 获取路由缓存管理器单例
|
|
299
|
-
*/ let routeCacheInstance = null;
|
|
300
|
-
function getRouteCache(config) {
|
|
301
|
-
if (!routeCacheInstance) {
|
|
302
|
-
routeCacheInstance = new RouteCache(config);
|
|
303
|
-
}
|
|
304
|
-
return routeCacheInstance;
|
|
305
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get RouteCache(){return RouteCache},get getRouteCache(){return getRouteCache}});const _logger=require("@vlian/logger");function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}let RouteCache=class RouteCache{async initPersistence(){try{if(typeof window!=="undefined"&&"indexedDB"in window){this.persistenceEnabled=true;await this.loadFromPersistence();_logger.logger.debug("路由缓存持久化已启用")}}catch(error){_logger.logger.warn("路由缓存持久化初始化失败",error);this.persistenceEnabled=false}}async loadFromPersistence(){try{}catch(error){_logger.logger.warn("从持久化存储加载缓存失败",error)}}async saveToPersistence(_key,_value){if(!this.persistenceEnabled){return}try{}catch(error){_logger.logger.warn("保存到持久化存储失败",error)}}generateKey(routes){if(typeof routes==="function"){return`fn_${routes.name||Math.random().toString(36).substring(7)}`}try{const routesStr=JSON.stringify(routes,(_key,value)=>{if(typeof value==="function"){return"[Function]"}return value});return`routes_${this.hashString(routesStr)}`}catch(error){return`routes_${Math.random().toString(36).substring(7)}`}}hashString(str){let hash=0;for(let i=0;i<str.length;i++){const char=str.charCodeAt(i);hash=(hash<<5)-hash+char;hash=hash&hash}return Math.abs(hash).toString(36)}isExpired(item){return Date.now()>item.expiresAt}cleanup(){for(const[key,item]of this.cache.entries()){if(this.isExpired(item)){this.cache.delete(key)}}for(const[key,item]of this.matchCache.entries()){if(this.isExpired(item)){this.matchCache.delete(key)}}this.evictLRU()}evictLRU(){if(this.cache.size>this.config.maxSize){const sorted=Array.from(this.cache.entries()).sort((a,b)=>a[1].lastAccessedAt-b[1].lastAccessedAt);const toDelete=sorted.slice(0,this.cache.size-this.config.maxSize);toDelete.forEach(([key])=>this.cache.delete(key))}if(this.matchCache.size>this.config.maxSize){const sorted=Array.from(this.matchCache.entries()).sort((a,b)=>a[1].lastAccessedAt-b[1].lastAccessedAt);const toDelete=sorted.slice(0,this.matchCache.size-this.config.maxSize);toDelete.forEach(([key])=>this.matchCache.delete(key))}}startCleanupInterval(){if(this.cleanupTimer){clearInterval(this.cleanupTimer)}this.cleanupTimer=setInterval(()=>{this.cleanup()},60*1e3)}get(routes){const key=this.generateKey(routes);const item=this.cache.get(key);if(!item){this.stats.transformMisses++;return null}if(this.isExpired(item)){this.cache.delete(key);this.stats.transformMisses++;return null}item.lastAccessedAt=Date.now();item.accessCount++;this.stats.transformHits++;return item.value}set(routes,value){const key=this.generateKey(routes);const now=Date.now();const item={value,expiresAt:now+this.config.ttl,createdAt:now,accessCount:0,lastAccessedAt:now};this.cache.set(key,item);if(this.persistenceEnabled){this.saveToPersistence(key,value).catch(error=>{_logger.logger.warn("保存缓存到持久化存储失败",error)})}this.evictLRU()}getMatch(path){const item=this.matchCache.get(path);if(!item){this.stats.matchMisses++;return undefined}if(this.isExpired(item)){this.matchCache.delete(path);this.stats.matchMisses++;return undefined}item.lastAccessedAt=Date.now();item.accessCount++;this.stats.matchHits++;return item.value}setMatch(path,route){const now=Date.now();const item={value:route,expiresAt:now+this.config.ttl,createdAt:now,accessCount:0,lastAccessedAt:now};this.matchCache.set(path,item);this.evictLRU()}clear(){this.cache.clear();this.matchCache.clear();this.stats={transformHits:0,transformMisses:0,matchHits:0,matchMisses:0};_logger.logger.debug("路由缓存已清空")}destroy(){this.clear();if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=null}}getStats(){const totalHits=this.stats.transformHits+this.stats.matchHits;const totalAccess=totalHits+this.stats.transformMisses+this.stats.matchMisses;const hitRate=totalAccess>0?totalHits/totalAccess:0;return{transformCacheSize:this.cache.size,matchCacheSize:this.matchCache.size,totalSize:this.cache.size+this.matchCache.size,hitRate}}constructor(config={}){_define_property(this,"cache",new Map);_define_property(this,"matchCache",new Map);_define_property(this,"config",void 0);_define_property(this,"persistenceEnabled",false);_define_property(this,"cleanupTimer",null);_define_property(this,"stats",{transformHits:0,transformMisses:0,matchHits:0,matchMisses:0});this.config={maxSize:config.maxSize??50,ttl:config.ttl??5*60*1e3,enablePersistence:config.enablePersistence??false,persistenceKeyPrefix:config.persistenceKeyPrefix??"router_cache_"};if(this.config.enablePersistence&&typeof window!=="undefined"&&"indexedDB"in window){this.initPersistence()}this.startCleanupInterval()}};let routeCacheInstance=null;function getRouteCache(config){if(!routeCacheInstance){routeCacheInstance=new RouteCache(config)}return routeCacheInstance}
|
|
@@ -1,292 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 路由预加载管理器
|
|
3
|
-
* 提供路由组件的预加载功能
|
|
4
|
-
*/ "use strict";
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
function _export(target, all) {
|
|
9
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
_export(exports, {
|
|
15
|
-
get PreloadStrategy () {
|
|
16
|
-
return PreloadStrategy;
|
|
17
|
-
},
|
|
18
|
-
get RoutePreloader () {
|
|
19
|
-
return RoutePreloader;
|
|
20
|
-
},
|
|
21
|
-
get getRoutePreloader () {
|
|
22
|
-
return getRoutePreloader;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
const _logger = require("@vlian/logger");
|
|
26
|
-
function _define_property(obj, key, value) {
|
|
27
|
-
if (key in obj) {
|
|
28
|
-
Object.defineProperty(obj, key, {
|
|
29
|
-
value: value,
|
|
30
|
-
enumerable: true,
|
|
31
|
-
configurable: true,
|
|
32
|
-
writable: true
|
|
33
|
-
});
|
|
34
|
-
} else {
|
|
35
|
-
obj[key] = value;
|
|
36
|
-
}
|
|
37
|
-
return obj;
|
|
38
|
-
}
|
|
39
|
-
var PreloadStrategy = /*#__PURE__*/ function(PreloadStrategy) {
|
|
40
|
-
/**
|
|
41
|
-
* 不预加载
|
|
42
|
-
*/ PreloadStrategy["NONE"] = "none";
|
|
43
|
-
/**
|
|
44
|
-
* 预加载当前路由的下一级路由
|
|
45
|
-
*/ PreloadStrategy["NEXT_LEVEL"] = "next-level";
|
|
46
|
-
/**
|
|
47
|
-
* 预加载所有路由
|
|
48
|
-
*/ PreloadStrategy["ALL"] = "all";
|
|
49
|
-
/**
|
|
50
|
-
* 预加载可见路由(根据路由配置的优先级)
|
|
51
|
-
*/ PreloadStrategy["VISIBLE"] = "visible";
|
|
52
|
-
return PreloadStrategy;
|
|
53
|
-
}({});
|
|
54
|
-
let RoutePreloader = class RoutePreloader {
|
|
55
|
-
/**
|
|
56
|
-
* 更新预加载配置
|
|
57
|
-
*/ updateConfig(config = {}) {
|
|
58
|
-
this.config = {
|
|
59
|
-
strategy: config.strategy ?? "none",
|
|
60
|
-
delay: config.delay ?? 1000,
|
|
61
|
-
priorityThreshold: config.priorityThreshold ?? 10,
|
|
62
|
-
timeout: config.timeout ?? 5000
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
shouldRegister(priority) {
|
|
66
|
-
if (this.config.strategy === "none") {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
if (this.config.strategy === "visible" && priority > this.config.priorityThreshold) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
registerTask(key, importFn, routeName, priority) {
|
|
75
|
-
if (!this.shouldRegister(priority)) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
this.tasks.set(key, {
|
|
79
|
-
importFn,
|
|
80
|
-
routeName,
|
|
81
|
-
priority,
|
|
82
|
-
status: 'pending'
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* 注册路由用于预加载
|
|
87
|
-
*/ registerRoute(route) {
|
|
88
|
-
if (!route.page && !route.layout) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const priority = route.handle?.order ?? 999;
|
|
92
|
-
// 注册页面组件
|
|
93
|
-
if (route.page && typeof route.page === 'function') {
|
|
94
|
-
this.registerTask(`${route.name}_page`, route.page, route.name, priority);
|
|
95
|
-
}
|
|
96
|
-
// 注册布局组件
|
|
97
|
-
if (route.layout && typeof route.layout === 'function') {
|
|
98
|
-
this.registerTask(`${route.name}_layout`, route.layout, route.name, priority);
|
|
99
|
-
}
|
|
100
|
-
// 递归注册子路由
|
|
101
|
-
if (route.children) {
|
|
102
|
-
route.children.forEach((child)=>this.registerRoute(child));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* 注册多个路由
|
|
107
|
-
*/ registerRoutes(routes, resolvers) {
|
|
108
|
-
const priorityByPath = new Map();
|
|
109
|
-
const nameByPath = new Map();
|
|
110
|
-
const collectPriority = (route)=>{
|
|
111
|
-
const priority = route.handle?.order ?? 999;
|
|
112
|
-
const routeName = route.name;
|
|
113
|
-
const record = (value)=>{
|
|
114
|
-
if (typeof value !== 'string') {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (!priorityByPath.has(value) || (priorityByPath.get(value) ?? 999) > priority) {
|
|
118
|
-
priorityByPath.set(value, priority);
|
|
119
|
-
nameByPath.set(value, routeName);
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
record(route.page);
|
|
123
|
-
record(route.layout);
|
|
124
|
-
record(route.error ?? route.errors);
|
|
125
|
-
record(route.loading);
|
|
126
|
-
route.children?.forEach(collectPriority);
|
|
127
|
-
};
|
|
128
|
-
routes.forEach(collectPriority);
|
|
129
|
-
routes.forEach((route)=>this.registerRoute(route));
|
|
130
|
-
if (!resolvers) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const registerResolverMap = (map, type)=>{
|
|
134
|
-
for (const [path, importFn] of map.entries()){
|
|
135
|
-
const routeName = nameByPath.get(path) ?? path;
|
|
136
|
-
const priority = priorityByPath.get(path) ?? 999;
|
|
137
|
-
this.registerTask(`${routeName}_${type}_${path}`, importFn, routeName, priority);
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
registerResolverMap(resolvers.pages, 'page');
|
|
141
|
-
registerResolverMap(resolvers.layouts, 'layout');
|
|
142
|
-
registerResolverMap(resolvers.errors, 'error');
|
|
143
|
-
registerResolverMap(resolvers.loadings, 'loading');
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* 预加载指定路由
|
|
147
|
-
*/ async preloadRoute(routeName) {
|
|
148
|
-
const tasks = Array.from(this.tasks.values()).filter((task)=>task.routeName === routeName && task.status === 'pending');
|
|
149
|
-
if (tasks.length === 0) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
await Promise.all(tasks.map((task)=>this.preloadTask(task)));
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* 预加载任务
|
|
156
|
-
*/ async preloadTask(task) {
|
|
157
|
-
if (task.status !== 'pending') {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
task.status = 'loading';
|
|
161
|
-
task.startTime = Date.now();
|
|
162
|
-
let timeoutId = null;
|
|
163
|
-
try {
|
|
164
|
-
// 设置超时
|
|
165
|
-
const timeoutPromise = new Promise((_, reject)=>{
|
|
166
|
-
timeoutId = setTimeout(()=>reject(new Error('预加载超时')), this.config.timeout);
|
|
167
|
-
});
|
|
168
|
-
// 执行预加载
|
|
169
|
-
await Promise.race([
|
|
170
|
-
task.importFn(),
|
|
171
|
-
timeoutPromise
|
|
172
|
-
]);
|
|
173
|
-
task.status = 'loaded';
|
|
174
|
-
const duration = Date.now() - (task.startTime || 0);
|
|
175
|
-
_logger.logger.debug(`路由组件预加载成功: ${task.routeName} (${duration}ms)`);
|
|
176
|
-
} catch (error) {
|
|
177
|
-
task.status = 'failed';
|
|
178
|
-
_logger.logger.warn(`路由组件预加载失败: ${task.routeName}`, error);
|
|
179
|
-
} finally{
|
|
180
|
-
if (timeoutId) {
|
|
181
|
-
clearTimeout(timeoutId);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* 开始预加载(根据策略)
|
|
187
|
-
*/ startPreload() {
|
|
188
|
-
if (this.config.strategy === "none") {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
this.stopPreload();
|
|
192
|
-
// 延迟预加载,避免影响初始渲染
|
|
193
|
-
this.preloadTimer = setTimeout(()=>{
|
|
194
|
-
const browserWindow = typeof window !== 'undefined' ? window : undefined;
|
|
195
|
-
if (browserWindow?.requestIdleCallback) {
|
|
196
|
-
this.idleHandle = browserWindow.requestIdleCallback(()=>{
|
|
197
|
-
this.executePreload();
|
|
198
|
-
});
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
this.executePreload();
|
|
202
|
-
}, this.config.delay);
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* 执行预加载
|
|
206
|
-
*/ async executePreload() {
|
|
207
|
-
const tasks = Array.from(this.tasks.values()).filter((task)=>task.status === 'pending').sort((a, b)=>a.priority - b.priority);
|
|
208
|
-
if (tasks.length === 0) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
_logger.logger.debug(`开始预加载 ${tasks.length} 个路由组件`);
|
|
212
|
-
// 根据策略决定预加载哪些任务
|
|
213
|
-
let tasksToPreload = [];
|
|
214
|
-
switch(this.config.strategy){
|
|
215
|
-
case "all":
|
|
216
|
-
tasksToPreload = tasks;
|
|
217
|
-
break;
|
|
218
|
-
case "next-level":
|
|
219
|
-
// 只预加载优先级最低的(最可能访问的)
|
|
220
|
-
tasksToPreload = tasks.slice(0, Math.min(5, tasks.length));
|
|
221
|
-
break;
|
|
222
|
-
case "visible":
|
|
223
|
-
tasksToPreload = tasks.filter((task)=>task.priority <= this.config.priorityThreshold);
|
|
224
|
-
break;
|
|
225
|
-
default:
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
// 并行预加载(限制并发数)
|
|
229
|
-
const concurrency = 3;
|
|
230
|
-
for(let i = 0; i < tasksToPreload.length; i += concurrency){
|
|
231
|
-
const batch = tasksToPreload.slice(i, i + concurrency);
|
|
232
|
-
await Promise.all(batch.map((task)=>this.preloadTask(task)));
|
|
233
|
-
}
|
|
234
|
-
_logger.logger.debug('路由组件预加载完成');
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* 停止预加载
|
|
238
|
-
*/ stopPreload() {
|
|
239
|
-
const browserWindow = typeof window !== 'undefined' ? window : undefined;
|
|
240
|
-
if (this.preloadTimer) {
|
|
241
|
-
clearTimeout(this.preloadTimer);
|
|
242
|
-
this.preloadTimer = null;
|
|
243
|
-
}
|
|
244
|
-
if (this.idleHandle !== null && browserWindow?.cancelIdleCallback) {
|
|
245
|
-
browserWindow.cancelIdleCallback(this.idleHandle);
|
|
246
|
-
this.idleHandle = null;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* 清空所有任务
|
|
251
|
-
*/ clear() {
|
|
252
|
-
this.tasks.clear();
|
|
253
|
-
this.stopPreload();
|
|
254
|
-
_logger.logger.debug('路由预加载任务已清空');
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* 获取预加载统计信息
|
|
258
|
-
*/ getStats() {
|
|
259
|
-
const stats = {
|
|
260
|
-
total: this.tasks.size,
|
|
261
|
-
pending: 0,
|
|
262
|
-
loading: 0,
|
|
263
|
-
loaded: 0,
|
|
264
|
-
failed: 0
|
|
265
|
-
};
|
|
266
|
-
for (const task of this.tasks.values()){
|
|
267
|
-
stats[task.status]++;
|
|
268
|
-
}
|
|
269
|
-
return stats;
|
|
270
|
-
}
|
|
271
|
-
constructor(config = {}){
|
|
272
|
-
_define_property(this, "tasks", new Map());
|
|
273
|
-
_define_property(this, "config", void 0);
|
|
274
|
-
_define_property(this, "preloadTimer", null);
|
|
275
|
-
_define_property(this, "idleHandle", null);
|
|
276
|
-
this.config = {
|
|
277
|
-
strategy: config.strategy ?? "none",
|
|
278
|
-
delay: config.delay ?? 1000,
|
|
279
|
-
priorityThreshold: config.priorityThreshold ?? 10,
|
|
280
|
-
timeout: config.timeout ?? 5000
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
/**
|
|
285
|
-
* 获取路由预加载管理器单例
|
|
286
|
-
*/ let routePreloaderInstance = null;
|
|
287
|
-
function getRoutePreloader(config) {
|
|
288
|
-
if (!routePreloaderInstance) {
|
|
289
|
-
routePreloaderInstance = new RoutePreloader(config);
|
|
290
|
-
}
|
|
291
|
-
return routePreloaderInstance;
|
|
292
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get PreloadStrategy(){return PreloadStrategy},get RoutePreloader(){return RoutePreloader},get getRoutePreloader(){return getRoutePreloader}});const _logger=require("@vlian/logger");function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}var PreloadStrategy=/*#__PURE__*/function(PreloadStrategy){PreloadStrategy["NONE"]="none";PreloadStrategy["NEXT_LEVEL"]="next-level";PreloadStrategy["ALL"]="all";PreloadStrategy["VISIBLE"]="visible";return PreloadStrategy}({});let RoutePreloader=class RoutePreloader{updateConfig(config={}){this.config={strategy:config.strategy??"none",delay:config.delay??1e3,priorityThreshold:config.priorityThreshold??10,timeout:config.timeout??5e3}}shouldRegister(priority){if(this.config.strategy==="none"){return false}if(this.config.strategy==="visible"&&priority>this.config.priorityThreshold){return false}return true}registerTask(key,importFn,routeName,priority){if(!this.shouldRegister(priority)){return}this.tasks.set(key,{importFn,routeName,priority,status:"pending"})}registerRoute(route){if(!route.page&&!route.layout){return}const priority=route.handle?.order??999;if(route.page&&typeof route.page==="function"){this.registerTask(`${route.name}_page`,route.page,route.name,priority)}if(route.layout&&typeof route.layout==="function"){this.registerTask(`${route.name}_layout`,route.layout,route.name,priority)}if(route.children){route.children.forEach(child=>this.registerRoute(child))}}registerRoutes(routes,resolvers){const priorityByPath=new Map;const nameByPath=new Map;const collectPriority=route=>{const priority=route.handle?.order??999;const routeName=route.name;const record=value=>{if(typeof value!=="string"){return}if(!priorityByPath.has(value)||(priorityByPath.get(value)??999)>priority){priorityByPath.set(value,priority);nameByPath.set(value,routeName)}};record(route.page);record(route.layout);record(route.error??route.errors);record(route.loading);route.children?.forEach(collectPriority)};routes.forEach(collectPriority);routes.forEach(route=>this.registerRoute(route));if(!resolvers){return}const registerResolverMap=(map,type)=>{for(const[path,importFn]of map.entries()){const routeName=nameByPath.get(path)??path;const priority=priorityByPath.get(path)??999;this.registerTask(`${routeName}_${type}_${path}`,importFn,routeName,priority)}};registerResolverMap(resolvers.pages,"page");registerResolverMap(resolvers.layouts,"layout");registerResolverMap(resolvers.errors,"error");registerResolverMap(resolvers.loadings,"loading")}async preloadRoute(routeName){const tasks=Array.from(this.tasks.values()).filter(task=>task.routeName===routeName&&task.status==="pending");if(tasks.length===0){return}await Promise.all(tasks.map(task=>this.preloadTask(task)))}async preloadTask(task){if(task.status!=="pending"){return}task.status="loading";task.startTime=Date.now();let timeoutId=null;try{const timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(new Error("预加载超时")),this.config.timeout)});await Promise.race([task.importFn(),timeoutPromise]);task.status="loaded";const duration=Date.now()-(task.startTime||0);_logger.logger.debug(`路由组件预加载成功: ${task.routeName} (${duration}ms)`)}catch(error){task.status="failed";_logger.logger.warn(`路由组件预加载失败: ${task.routeName}`,error)}finally{if(timeoutId){clearTimeout(timeoutId)}}}startPreload(){if(this.config.strategy==="none"){return}this.stopPreload();this.preloadTimer=setTimeout(()=>{const browserWindow=typeof window!=="undefined"?window:undefined;if(browserWindow?.requestIdleCallback){this.idleHandle=browserWindow.requestIdleCallback(()=>{this.executePreload()});return}this.executePreload()},this.config.delay)}async executePreload(){const tasks=Array.from(this.tasks.values()).filter(task=>task.status==="pending").sort((a,b)=>a.priority-b.priority);if(tasks.length===0){return}_logger.logger.debug(`开始预加载 ${tasks.length} 个路由组件`);let tasksToPreload=[];switch(this.config.strategy){case"all":tasksToPreload=tasks;break;case"next-level":tasksToPreload=tasks.slice(0,Math.min(5,tasks.length));break;case"visible":tasksToPreload=tasks.filter(task=>task.priority<=this.config.priorityThreshold);break;default:return}const concurrency=3;for(let i=0;i<tasksToPreload.length;i+=concurrency){const batch=tasksToPreload.slice(i,i+concurrency);await Promise.all(batch.map(task=>this.preloadTask(task)))}_logger.logger.debug("路由组件预加载完成")}stopPreload(){const browserWindow=typeof window!=="undefined"?window:undefined;if(this.preloadTimer){clearTimeout(this.preloadTimer);this.preloadTimer=null}if(this.idleHandle!==null&&browserWindow?.cancelIdleCallback){browserWindow.cancelIdleCallback(this.idleHandle);this.idleHandle=null}}clear(){this.tasks.clear();this.stopPreload();_logger.logger.debug("路由预加载任务已清空")}getStats(){const stats={total:this.tasks.size,pending:0,loading:0,loaded:0,failed:0};for(const task of this.tasks.values()){stats[task.status]++}return stats}constructor(config={}){_define_property(this,"tasks",new Map);_define_property(this,"config",void 0);_define_property(this,"preloadTimer",null);_define_property(this,"idleHandle",null);this.config={strategy:config.strategy??"none",delay:config.delay??1e3,priorityThreshold:config.priorityThreshold??10,timeout:config.timeout??5e3}}};let routePreloaderInstance=null;function getRoutePreloader(config){if(!routePreloaderInstance){routePreloaderInstance=new RoutePreloader(config)}return routePreloaderInstance}
|
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 路由性能优化模块入口
|
|
3
|
-
*/ "use strict";
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
_export_star(require("./RouteCache"), exports);
|
|
8
|
-
_export_star(require("./RoutePreloader"), exports);
|
|
9
|
-
function _export_star(from, to) {
|
|
10
|
-
Object.keys(from).forEach(function(k) {
|
|
11
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
12
|
-
Object.defineProperty(to, k, {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function() {
|
|
15
|
-
return from[k];
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
return from;
|
|
21
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});_export_star(require("./RouteCache"),exports);_export_star(require("./RoutePreloader"),exports);function _export_star(from,to){Object.keys(from).forEach(function(k){if(k!=="default"&&!Object.prototype.hasOwnProperty.call(to,k)){Object.defineProperty(to,k,{enumerable:true,get:function(){return from[k]}})}});return from}
|