@lytjs/ssr 6.0.0 → 6.5.0
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/README.md +589 -0
- package/dist/index.cjs +485 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +247 -7
- package/dist/index.d.ts +247 -7
- package/dist/index.mjs +473 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -113,6 +113,7 @@ var VirtualList = component.defineComponent({
|
|
|
113
113
|
buffer: { type: Number, default: 5 },
|
|
114
114
|
class: { type: String, default: "" }
|
|
115
115
|
},
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
117
|
setup(props, { slots }) {
|
|
117
118
|
const scrollTop = reactivity.signal(0);
|
|
118
119
|
const visibleCount = reactivity.computedSignal(() => {
|
|
@@ -146,6 +147,7 @@ var VirtualList = component.defineComponent({
|
|
|
146
147
|
return () => {
|
|
147
148
|
const items = visibleData().map((item, index) => {
|
|
148
149
|
const actualIndex = startIndex() + index;
|
|
150
|
+
const slotContent = slots?.default?.({ item, index: actualIndex });
|
|
149
151
|
return vdom.createVNode(
|
|
150
152
|
"div",
|
|
151
153
|
{
|
|
@@ -153,7 +155,7 @@ var VirtualList = component.defineComponent({
|
|
|
153
155
|
style: `height: ${props.itemHeight}px;`,
|
|
154
156
|
"data-index": actualIndex
|
|
155
157
|
},
|
|
156
|
-
|
|
158
|
+
slotContent
|
|
157
159
|
);
|
|
158
160
|
});
|
|
159
161
|
return vdom.createVNode(
|
|
@@ -187,6 +189,38 @@ var VirtualList = component.defineComponent({
|
|
|
187
189
|
}
|
|
188
190
|
});
|
|
189
191
|
var DEFAULT_CHUNK_SIZE = 4096;
|
|
192
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
193
|
+
var DEFAULT_FALLBACK_HTML = '<div id="lyt-fallback">\u670D\u52A1\u6B63\u5728\u52A0\u8F7D\u4E2D...</div>';
|
|
194
|
+
var StreamTimeoutError = class extends Error {
|
|
195
|
+
constructor(message = "Stream rendering timeout") {
|
|
196
|
+
super(message);
|
|
197
|
+
this.name = "StreamTimeoutError";
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
var FlowController = class {
|
|
201
|
+
constructor(maxBytesPerSecond) {
|
|
202
|
+
this.bytesSentInSecond = 0;
|
|
203
|
+
this.lastSecondTimestamp = Date.now();
|
|
204
|
+
this.maxBytesPerSecond = maxBytesPerSecond;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 尝试发送字节,如超出速率则等待
|
|
208
|
+
*/
|
|
209
|
+
async waitForRateLimit(byteCount) {
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
if (now - this.lastSecondTimestamp >= 1e3) {
|
|
212
|
+
this.bytesSentInSecond = 0;
|
|
213
|
+
this.lastSecondTimestamp = now;
|
|
214
|
+
}
|
|
215
|
+
if (this.bytesSentInSecond + byteCount > this.maxBytesPerSecond) {
|
|
216
|
+
const waitTime = 1e3 - (now - this.lastSecondTimestamp);
|
|
217
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
218
|
+
this.bytesSentInSecond = 0;
|
|
219
|
+
this.lastSecondTimestamp = Date.now();
|
|
220
|
+
}
|
|
221
|
+
this.bytesSentInSecond += byteCount;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
190
224
|
var SUSPENSE_TYPE = "Suspense";
|
|
191
225
|
function isSuspenseVNode(vnode) {
|
|
192
226
|
return commonIs.isObject(vnode) && (typeof vnode.type === "object" && vnode.type !== null && "__suspense" in vnode.type || commonIs.isString(vnode.type) && vnode.type === SUSPENSE_TYPE);
|
|
@@ -258,11 +292,32 @@ function renderToStream(vnode, options) {
|
|
|
258
292
|
const {
|
|
259
293
|
chunkSize = DEFAULT_CHUNK_SIZE,
|
|
260
294
|
onShellReady,
|
|
261
|
-
onError
|
|
295
|
+
onError,
|
|
296
|
+
timeout = DEFAULT_TIMEOUT,
|
|
297
|
+
fallbackHtml = DEFAULT_FALLBACK_HTML,
|
|
298
|
+
maxBytesPerSecond,
|
|
299
|
+
errorRecovery = true
|
|
262
300
|
} = options || {};
|
|
263
301
|
const encoder = new TextEncoder();
|
|
302
|
+
const flowController = maxBytesPerSecond ? new FlowController(maxBytesPerSecond) : null;
|
|
303
|
+
let timeoutId = null;
|
|
264
304
|
return new ReadableStream({
|
|
265
305
|
start(controller) {
|
|
306
|
+
timeoutId = setTimeout(() => {
|
|
307
|
+
try {
|
|
308
|
+
if (errorRecovery) {
|
|
309
|
+
console.warn("Stream rendering timed out, using fallback HTML");
|
|
310
|
+
controller.enqueue(encoder.encode(fallbackHtml));
|
|
311
|
+
controller.close();
|
|
312
|
+
onError?.(new StreamTimeoutError("Stream rendering timed out"));
|
|
313
|
+
} else {
|
|
314
|
+
controller.error(new StreamTimeoutError("Stream rendering timed out"));
|
|
315
|
+
}
|
|
316
|
+
} catch (err) {
|
|
317
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
318
|
+
onError?.(error);
|
|
319
|
+
}
|
|
320
|
+
}, timeout);
|
|
266
321
|
try {
|
|
267
322
|
const suspenseBoundaryIndex = [];
|
|
268
323
|
const chunks = collectChunks(vnode, suspenseBoundaryIndex);
|
|
@@ -273,29 +328,64 @@ function renderToStream(vnode, options) {
|
|
|
273
328
|
const shellHtml = shellChunks.join("");
|
|
274
329
|
const byteChunks = splitIntoByteChunks(shellHtml, chunkSize);
|
|
275
330
|
for (const chunk of byteChunks) {
|
|
276
|
-
controller
|
|
331
|
+
sendChunk(controller, encoder, chunk);
|
|
277
332
|
}
|
|
278
333
|
onShellReady?.();
|
|
279
334
|
const remainingChunks = chunks.slice(shellBoundary);
|
|
280
335
|
const remainingHtml = remainingChunks.join("");
|
|
281
336
|
const remainingByteChunks = splitIntoByteChunks(remainingHtml, chunkSize);
|
|
282
337
|
for (const chunk of remainingByteChunks) {
|
|
283
|
-
controller
|
|
338
|
+
sendChunk(controller, encoder, chunk);
|
|
284
339
|
}
|
|
285
340
|
} else {
|
|
286
341
|
const byteChunks = splitIntoByteChunks(fullHtml, chunkSize);
|
|
287
342
|
for (const chunk of byteChunks) {
|
|
288
|
-
controller
|
|
343
|
+
sendChunk(controller, encoder, chunk);
|
|
289
344
|
}
|
|
290
345
|
}
|
|
346
|
+
if (timeoutId) {
|
|
347
|
+
clearTimeout(timeoutId);
|
|
348
|
+
timeoutId = null;
|
|
349
|
+
}
|
|
291
350
|
controller.close();
|
|
292
351
|
} catch (err) {
|
|
352
|
+
if (timeoutId) {
|
|
353
|
+
clearTimeout(timeoutId);
|
|
354
|
+
timeoutId = null;
|
|
355
|
+
}
|
|
293
356
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
294
357
|
onError?.(error);
|
|
295
|
-
|
|
358
|
+
if (errorRecovery) {
|
|
359
|
+
try {
|
|
360
|
+
console.warn("Error occurred during stream rendering, using fallback HTML");
|
|
361
|
+
controller.enqueue(encoder.encode(fallbackHtml));
|
|
362
|
+
controller.close();
|
|
363
|
+
} catch (_) {
|
|
364
|
+
controller.error(error);
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
controller.error(error);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
cancel(reason) {
|
|
372
|
+
if (timeoutId) {
|
|
373
|
+
clearTimeout(timeoutId);
|
|
296
374
|
}
|
|
375
|
+
console.warn("Stream cancelled:", reason);
|
|
297
376
|
}
|
|
298
377
|
});
|
|
378
|
+
function sendChunk(controller, encoder2, chunk) {
|
|
379
|
+
const encoded = encoder2.encode(chunk);
|
|
380
|
+
if (flowController) {
|
|
381
|
+
(async () => {
|
|
382
|
+
await flowController.waitForRateLimit(encoded.length);
|
|
383
|
+
controller.enqueue(encoded);
|
|
384
|
+
})();
|
|
385
|
+
} else {
|
|
386
|
+
controller.enqueue(encoded);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
299
389
|
}
|
|
300
390
|
function renderToStreamAsync(vnode, options) {
|
|
301
391
|
const {
|
|
@@ -437,7 +527,12 @@ var DEFAULT_SSG_OPTIONS = {
|
|
|
437
527
|
siteName: "LytJS Site",
|
|
438
528
|
hashMode: false,
|
|
439
529
|
globalScripts: [],
|
|
440
|
-
globalStyles: []
|
|
530
|
+
globalStyles: [],
|
|
531
|
+
isr: {
|
|
532
|
+
revalidate: 60,
|
|
533
|
+
enabled: false,
|
|
534
|
+
fallback: false
|
|
535
|
+
}
|
|
441
536
|
};
|
|
442
537
|
function normalizePath(path) {
|
|
443
538
|
let normalized = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -556,6 +651,376 @@ function validatePages(pages) {
|
|
|
556
651
|
}
|
|
557
652
|
return errors;
|
|
558
653
|
}
|
|
654
|
+
var ISRCacheManager = class {
|
|
655
|
+
constructor() {
|
|
656
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
657
|
+
this.revalidateTasks = /* @__PURE__ */ new Map();
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* 获取缓存的页面
|
|
661
|
+
*/
|
|
662
|
+
get(path) {
|
|
663
|
+
return this.cache.get(path);
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* 设置缓存
|
|
667
|
+
*/
|
|
668
|
+
set(path, html) {
|
|
669
|
+
this.cache.set(path, {
|
|
670
|
+
html,
|
|
671
|
+
timestamp: Date.now(),
|
|
672
|
+
isRevalidating: false
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* 检查是否需要重新验证
|
|
677
|
+
*/
|
|
678
|
+
needsRevalidation(path, revalidateSeconds) {
|
|
679
|
+
const entry = this.cache.get(path);
|
|
680
|
+
if (!entry) return true;
|
|
681
|
+
const age = (Date.now() - entry.timestamp) / 1e3;
|
|
682
|
+
return age > revalidateSeconds && !entry.isRevalidating;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* 标记为正在重新生成
|
|
686
|
+
*/
|
|
687
|
+
markRevalidating(path) {
|
|
688
|
+
const entry = this.cache.get(path);
|
|
689
|
+
if (entry) {
|
|
690
|
+
entry.isRevalidating = true;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* 完成重新生成
|
|
695
|
+
*/
|
|
696
|
+
finishRevalidation(path, html) {
|
|
697
|
+
this.set(path, html);
|
|
698
|
+
this.revalidateTasks.delete(path);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* 获取正在进行的重新生成任务
|
|
702
|
+
*/
|
|
703
|
+
getRevalidateTask(path) {
|
|
704
|
+
return this.revalidateTasks.get(path);
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* 设置重新生成任务
|
|
708
|
+
*/
|
|
709
|
+
setRevalidateTask(path, task) {
|
|
710
|
+
this.revalidateTasks.set(path, task);
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* 清除过期的缓存
|
|
714
|
+
*/
|
|
715
|
+
clearExpired(maxAgeSeconds) {
|
|
716
|
+
const now = Date.now();
|
|
717
|
+
let cleared = 0;
|
|
718
|
+
for (const [path, entry] of this.cache) {
|
|
719
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
720
|
+
if (age > maxAgeSeconds) {
|
|
721
|
+
this.cache.delete(path);
|
|
722
|
+
cleared++;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return cleared;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* 获取缓存统计信息
|
|
729
|
+
*/
|
|
730
|
+
getStats() {
|
|
731
|
+
return {
|
|
732
|
+
total: this.cache.size,
|
|
733
|
+
paths: Array.from(this.cache.keys())
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
var isrCache = new ISRCacheManager();
|
|
738
|
+
function createISRMiddleware(options) {
|
|
739
|
+
const { staticPages, revalidate = 60, enabled = true, regenerate } = options;
|
|
740
|
+
for (const [path, html] of staticPages) {
|
|
741
|
+
isrCache.set(path, html);
|
|
742
|
+
}
|
|
743
|
+
return async (req, res, next) => {
|
|
744
|
+
if (!enabled) {
|
|
745
|
+
return next();
|
|
746
|
+
}
|
|
747
|
+
let path = req.path;
|
|
748
|
+
if (path.endsWith("/")) {
|
|
749
|
+
path = path + "index.html";
|
|
750
|
+
} else if (!path.endsWith(".html")) {
|
|
751
|
+
path = path + "/index.html";
|
|
752
|
+
}
|
|
753
|
+
const cached = isrCache.get(path);
|
|
754
|
+
if (cached) {
|
|
755
|
+
res.setHeader("Cache-Control", `s-maxage=${revalidate}, stale-while-revalidate`);
|
|
756
|
+
res.setHeader("X-ISR-Cache", "HIT");
|
|
757
|
+
res.setHeader("X-ISR-Timestamp", cached.timestamp.toString());
|
|
758
|
+
res.send(cached.html);
|
|
759
|
+
if (isrCache.needsRevalidation(path, revalidate) && regenerate) {
|
|
760
|
+
isrCache.markRevalidating(path);
|
|
761
|
+
try {
|
|
762
|
+
const newHtml = await regenerate(path);
|
|
763
|
+
isrCache.finishRevalidation(path, newHtml);
|
|
764
|
+
} catch (error) {
|
|
765
|
+
console.error("[ISR] Revalidation failed for", path, error);
|
|
766
|
+
const entry = isrCache.get(path);
|
|
767
|
+
if (entry) {
|
|
768
|
+
entry.isRevalidating = false;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
} else {
|
|
773
|
+
if (regenerate) {
|
|
774
|
+
try {
|
|
775
|
+
const html = await regenerate(path);
|
|
776
|
+
isrCache.set(path, html);
|
|
777
|
+
res.setHeader("X-ISR-Cache", "MISS");
|
|
778
|
+
res.send(html);
|
|
779
|
+
} catch (error) {
|
|
780
|
+
next(error);
|
|
781
|
+
}
|
|
782
|
+
} else {
|
|
783
|
+
next();
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
async function revalidateOnDemand(path, regenerate) {
|
|
789
|
+
const existingTask = isrCache.getRevalidateTask(path);
|
|
790
|
+
if (existingTask) {
|
|
791
|
+
return existingTask;
|
|
792
|
+
}
|
|
793
|
+
const task = (async () => {
|
|
794
|
+
isrCache.markRevalidating(path);
|
|
795
|
+
try {
|
|
796
|
+
const html = await regenerate();
|
|
797
|
+
isrCache.finishRevalidation(path, html);
|
|
798
|
+
return html;
|
|
799
|
+
} catch (error) {
|
|
800
|
+
const entry = isrCache.get(path);
|
|
801
|
+
if (entry) {
|
|
802
|
+
entry.isRevalidating = false;
|
|
803
|
+
}
|
|
804
|
+
throw error;
|
|
805
|
+
}
|
|
806
|
+
})();
|
|
807
|
+
isrCache.setRevalidateTask(path, task);
|
|
808
|
+
return task;
|
|
809
|
+
}
|
|
810
|
+
function getISRCacheStats() {
|
|
811
|
+
return isrCache.getStats();
|
|
812
|
+
}
|
|
813
|
+
function clearISRCache(path, maxAge) {
|
|
814
|
+
if (path) {
|
|
815
|
+
const cache = isrCache.cache;
|
|
816
|
+
cache.delete(path);
|
|
817
|
+
} else if (maxAge) {
|
|
818
|
+
isrCache.clearExpired(maxAge);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
var ServerComponentStateManager = class {
|
|
822
|
+
constructor() {
|
|
823
|
+
/** 注册的组件 */
|
|
824
|
+
this.registrations = /* @__PURE__ */ new Map();
|
|
825
|
+
/** 正在执行的预取请求 */
|
|
826
|
+
this.pendingPrefetches = /* @__PURE__ */ new Map();
|
|
827
|
+
/** 组件初始化状态 */
|
|
828
|
+
this.initializationStates = /* @__PURE__ */ new Map();
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* 注册服务端组件
|
|
832
|
+
*/
|
|
833
|
+
register(name, registration) {
|
|
834
|
+
this.registrations.set(name, registration);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* 取消注册服务端组件
|
|
838
|
+
*/
|
|
839
|
+
unregister(name) {
|
|
840
|
+
this.registrations.delete(name);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* 获取已注册的组件
|
|
844
|
+
*/
|
|
845
|
+
getRegistration(name) {
|
|
846
|
+
return this.registrations.get(name);
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* 初始化服务端组件
|
|
850
|
+
*/
|
|
851
|
+
async initializeComponent(name, context) {
|
|
852
|
+
const registration = this.registrations.get(name);
|
|
853
|
+
if (!registration) {
|
|
854
|
+
throw new Error(`Server component ${name} not registered`);
|
|
855
|
+
}
|
|
856
|
+
if (this.initializationStates.get(name)) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
if (registration.onServerInit) {
|
|
860
|
+
await Promise.resolve(registration.onServerInit(context));
|
|
861
|
+
}
|
|
862
|
+
this.initializationStates.set(name, true);
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* 清理服务端组件
|
|
866
|
+
*/
|
|
867
|
+
async cleanupComponent(name, context) {
|
|
868
|
+
const registration = this.registrations.get(name);
|
|
869
|
+
if (!registration) {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if (registration.onServerCleanup) {
|
|
873
|
+
await Promise.resolve(registration.onServerCleanup(context));
|
|
874
|
+
}
|
|
875
|
+
this.initializationStates.delete(name);
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* 预取组件数据(带缓存)
|
|
879
|
+
*/
|
|
880
|
+
async prefetchComponentData(name, context, cacheKey) {
|
|
881
|
+
const registration = this.registrations.get(name);
|
|
882
|
+
if (!registration || !registration.prefetch) {
|
|
883
|
+
return { data: {} };
|
|
884
|
+
}
|
|
885
|
+
const key = cacheKey || `${name}-${JSON.stringify(context)}`;
|
|
886
|
+
const existing = this.pendingPrefetches.get(key);
|
|
887
|
+
if (existing) {
|
|
888
|
+
return existing;
|
|
889
|
+
}
|
|
890
|
+
const promise = registration.prefetch(context).finally(() => {
|
|
891
|
+
this.pendingPrefetches.delete(key);
|
|
892
|
+
});
|
|
893
|
+
this.pendingPrefetches.set(key, promise);
|
|
894
|
+
return promise;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* 清除所有缓存
|
|
898
|
+
*/
|
|
899
|
+
clearAll() {
|
|
900
|
+
this.registrations.clear();
|
|
901
|
+
this.pendingPrefetches.clear();
|
|
902
|
+
this.initializationStates.clear();
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
var stateManager = new ServerComponentStateManager();
|
|
906
|
+
function registerServerComponent(name, registration) {
|
|
907
|
+
stateManager.register(name, registration);
|
|
908
|
+
}
|
|
909
|
+
function unregisterServerComponent(name) {
|
|
910
|
+
stateManager.unregister(name);
|
|
911
|
+
}
|
|
912
|
+
function collectPrefetchComponents(vnode) {
|
|
913
|
+
const components = [];
|
|
914
|
+
collectComponentsRecursive(vnode, components);
|
|
915
|
+
return components;
|
|
916
|
+
}
|
|
917
|
+
function collectComponentsRecursive(vnode, result) {
|
|
918
|
+
if (!commonIs.isObject(vnode)) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
const node = vnode;
|
|
922
|
+
if (commonIs.isArray(vnode)) {
|
|
923
|
+
for (const child of vnode) {
|
|
924
|
+
collectComponentsRecursive(child, result);
|
|
925
|
+
}
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
if (commonIs.isFunction(node.type)) {
|
|
929
|
+
const compName = node.type.name;
|
|
930
|
+
if (compName && stateManager.getRegistration(compName)) {
|
|
931
|
+
if (!result.includes(compName)) {
|
|
932
|
+
result.push(compName);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
const children = node.children;
|
|
937
|
+
if (commonIs.isArray(children)) {
|
|
938
|
+
for (const child of children) {
|
|
939
|
+
collectComponentsRecursive(child, result);
|
|
940
|
+
}
|
|
941
|
+
} else if (commonIs.isObject(children)) {
|
|
942
|
+
collectComponentsRecursive(children, result);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
async function prefetchAllComponents(components, context) {
|
|
946
|
+
const results = {};
|
|
947
|
+
const promises = [];
|
|
948
|
+
for (const name of components) {
|
|
949
|
+
const promise = stateManager.prefetchComponentData(name, context).then((result) => {
|
|
950
|
+
results[name] = result;
|
|
951
|
+
}).catch((err) => {
|
|
952
|
+
console.warn(`Prefetch failed for component ${name}`, err);
|
|
953
|
+
results[name] = { data: {} };
|
|
954
|
+
});
|
|
955
|
+
promises.push(promise);
|
|
956
|
+
}
|
|
957
|
+
await Promise.all(promises);
|
|
958
|
+
return results;
|
|
959
|
+
}
|
|
960
|
+
function safeSerializeState(state) {
|
|
961
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
962
|
+
return JSON.stringify(state, (_key, value) => {
|
|
963
|
+
if (typeof value === "object" && value !== null) {
|
|
964
|
+
if (seen.has(value)) {
|
|
965
|
+
return "[Circular]";
|
|
966
|
+
}
|
|
967
|
+
seen.add(value);
|
|
968
|
+
}
|
|
969
|
+
if (value instanceof Date) {
|
|
970
|
+
return { __type: "Date", value: value.toISOString() };
|
|
971
|
+
}
|
|
972
|
+
if (value instanceof RegExp) {
|
|
973
|
+
return { __type: "RegExp", source: value.source, flags: value.flags };
|
|
974
|
+
}
|
|
975
|
+
if (value instanceof Set) {
|
|
976
|
+
return { __type: "Set", values: Array.from(value) };
|
|
977
|
+
}
|
|
978
|
+
if (value instanceof Map) {
|
|
979
|
+
return { __type: "Map", entries: Array.from(value.entries()) };
|
|
980
|
+
}
|
|
981
|
+
return value;
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
function safeDeserializeState(serialized) {
|
|
985
|
+
return JSON.parse(serialized, (_key, value) => {
|
|
986
|
+
if (typeof value === "object" && value !== null && "__type" in value) {
|
|
987
|
+
const typedValue = value;
|
|
988
|
+
switch (typedValue.__type) {
|
|
989
|
+
case "Date":
|
|
990
|
+
return new Date(typedValue.value);
|
|
991
|
+
case "RegExp":
|
|
992
|
+
return new RegExp(typedValue.source, typedValue.flags);
|
|
993
|
+
case "Set":
|
|
994
|
+
return new Set(typedValue.values);
|
|
995
|
+
case "Map":
|
|
996
|
+
return new Map(typedValue.entries);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
return value;
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
function buildDehydratedState(prefetchResults) {
|
|
1003
|
+
const state = {};
|
|
1004
|
+
for (const [name, result] of Object.entries(prefetchResults)) {
|
|
1005
|
+
state[name] = {
|
|
1006
|
+
componentName: name,
|
|
1007
|
+
props: {},
|
|
1008
|
+
data: result.data
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
return state;
|
|
1012
|
+
}
|
|
1013
|
+
function ServerComponent(options) {
|
|
1014
|
+
return function(target) {
|
|
1015
|
+
registerServerComponent(options.name, {
|
|
1016
|
+
name: options.name,
|
|
1017
|
+
render: target.render || (() => ({ type: "div" })),
|
|
1018
|
+
prefetch: options.prefetch,
|
|
1019
|
+
onServerInit: options.onInit,
|
|
1020
|
+
onServerCleanup: options.onCleanup
|
|
1021
|
+
});
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
559
1024
|
var HYDRATE_ATTR = "data-hydrate";
|
|
560
1025
|
var HYDRATE_STRATEGY_ATTR = "data-hydrate-strategy";
|
|
561
1026
|
var DEHYDRATED_STATE_ID = "__LYT_DEHYDRATED_STATE__";
|
|
@@ -721,20 +1186,33 @@ function createDehydratedState(vnode, initialState) {
|
|
|
721
1186
|
return `<script id="${DEHYDRATED_STATE_ID}" type="application/json">${safeJson}</script>`;
|
|
722
1187
|
}
|
|
723
1188
|
|
|
1189
|
+
exports.ServerComponent = ServerComponent;
|
|
724
1190
|
exports.VirtualList = VirtualList;
|
|
1191
|
+
exports.buildDehydratedState = buildDehydratedState;
|
|
1192
|
+
exports.clearISRCache = clearISRCache;
|
|
1193
|
+
exports.collectPrefetchComponents = collectPrefetchComponents;
|
|
725
1194
|
exports.createDehydratedState = createDehydratedState;
|
|
726
1195
|
exports.createHydrationMarkers = createHydrationMarkers;
|
|
1196
|
+
exports.createISRMiddleware = createISRMiddleware;
|
|
727
1197
|
exports.default = render_default;
|
|
728
1198
|
exports.generateRouteManifest = generateRouteManifest;
|
|
729
1199
|
exports.generateStaticPages = generateStaticPages;
|
|
730
1200
|
exports.getHydrationStrategy = getHydrationStrategy;
|
|
1201
|
+
exports.getISRCacheStats = getISRCacheStats;
|
|
1202
|
+
exports.prefetchAllComponents = prefetchAllComponents;
|
|
1203
|
+
exports.registerServerComponent = registerServerComponent;
|
|
731
1204
|
exports.renderToHtml = renderToHtml;
|
|
732
1205
|
exports.renderToStream = renderToStream;
|
|
733
1206
|
exports.renderToStreamAsync = renderToStreamAsync;
|
|
734
1207
|
exports.renderToStreamEnhanced = renderToStreamEnhanced;
|
|
735
1208
|
exports.renderToString = renderToString;
|
|
736
1209
|
exports.resetComponentIdCounter = resetComponentIdCounter;
|
|
1210
|
+
exports.revalidateOnDemand = revalidateOnDemand;
|
|
1211
|
+
exports.safeDeserializeState = safeDeserializeState;
|
|
1212
|
+
exports.safeSerializeState = safeSerializeState;
|
|
737
1213
|
exports.serializeHydrationState = serializeHydrationState;
|
|
1214
|
+
exports.stateManager = stateManager;
|
|
1215
|
+
exports.unregisterServerComponent = unregisterServerComponent;
|
|
738
1216
|
exports.validatePages = validatePages;
|
|
739
1217
|
exports.writeStaticFiles = writeStaticFiles;
|
|
740
1218
|
//# sourceMappingURL=index.cjs.map
|