@lytjs/ssr 6.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/render.ts","../src/virtualList.ts","../src/stream.ts","../src/ssg.ts","../src/hydration.ts"],"names":["computed","isObject","isString","isNumber","isArray","isFunction","fs"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * @lytjs/ssr - 服务端渲染\r\n *\r\n * 将 VNode 渲染为 HTML 字符串\r\n */\r\n\r\nimport type { VNode } from '@lytjs/vdom';\r\nimport { isString, isNumber, isArray, isObject, isFunction } from '@lytjs/common-is';\r\n\r\n/**\r\n * 转义 HTML 特殊字符\r\n */\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#39;');\r\n}\r\n\r\n/**\r\n * 渲染 VNode 为 HTML 字符串\r\n */\r\nexport function renderToString(vnode: VNode | VNode[] | string | number | null | undefined): string {\r\n // 处理 null/undefined\r\n if (vnode === null || vnode === undefined) {\r\n return '';\r\n }\r\n\r\n // 处理字符串\r\n if (isString(vnode)) {\r\n return escapeHtml(vnode);\r\n }\r\n\r\n // 处理数字\r\n if (isNumber(vnode)) {\r\n return String(vnode);\r\n }\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n return vnode.map(child => renderToString(child)).join('');\r\n }\r\n\r\n // 处理 VNode 对象\r\n if (!isObject(vnode)) {\r\n return '';\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 处理文本节点\r\n if (node.type === 'text' || typeof node.type === 'symbol') {\r\n return escapeHtml(String(node.children || ''));\r\n }\r\n\r\n // 处理组件\r\n if (isFunction(node.type)) {\r\n // 简化处理:组件返回空字符串\r\n return '';\r\n }\r\n\r\n // 处理元素\r\n if (isString(node.type)) {\r\n const tag = node.type;\r\n const props = node.props || {};\r\n \r\n // 自闭合标签\r\n const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];\r\n if (voidTags.includes(tag)) {\r\n return `<${tag}${renderAttributes(props)}>`;\r\n }\r\n\r\n // 渲染子元素\r\n const children = renderToString(node.children as any);\r\n\r\n return `<${tag}${renderAttributes(props)}>${children}</${tag}>`;\r\n }\r\n\r\n return '';\r\n}\r\n\r\n/**\r\n * 渲染属性为 HTML 属性字符串\r\n */\r\nfunction renderAttributes(props: Record<string, any>): string {\r\n const attrs: string[] = [];\r\n\r\n for (const [key, value] of Object.entries(props)) {\r\n // 跳过事件处理器和内部属性\r\n if (key.startsWith('on') || key === 'key' || key === 'ref') {\r\n continue;\r\n }\r\n\r\n // 处理 class\r\n if (key === 'class' || key === 'className') {\r\n if (value) {\r\n const classValue = isObject(value) \r\n ? Object.entries(value).filter(([, v]) => v).map(([k]) => k).join(' ')\r\n : String(value);\r\n if (classValue) {\r\n attrs.push(` class=\"${escapeHtml(classValue)}\"`);\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n // 处理 style\r\n if (key === 'style') {\r\n if (value) {\r\n const styleValue = isObject(value)\r\n ? Object.entries(value).map(([k, v]) => `${k}:${v}`).join(';')\r\n : String(value);\r\n if (styleValue) {\r\n attrs.push(` style=\"${escapeHtml(styleValue)}\"`);\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n // 处理布尔属性\r\n if (value === true) {\r\n attrs.push(` ${key}`);\r\n continue;\r\n }\r\n\r\n // 跳过 false 和 null\r\n if (value === false || value === null || value === undefined) {\r\n continue;\r\n }\r\n\r\n // 普通属性\r\n attrs.push(` ${key}=\"${escapeHtml(String(value))}\"`);\r\n }\r\n\r\n return attrs.join('');\r\n}\r\n\r\n/**\r\n * 渲染完整的 HTML 页面\r\n */\r\nexport function renderToHtml(\r\n vnode: VNode | VNode[],\r\n options: {\r\n title?: string;\r\n lang?: string;\r\n head?: string;\r\n bodyAttrs?: Record<string, string>;\r\n } = {}\r\n): string {\r\n const { title = 'LytJS App', lang = 'zh-CN', head = '', bodyAttrs = {} } = options;\r\n\r\n const content = renderToString(vnode);\r\n const bodyAttrsStr = Object.entries(bodyAttrs)\r\n .map(([k, v]) => ` ${k}=\"${escapeHtml(v)}\"`)\r\n .join('');\r\n\r\n return `<!DOCTYPE html>\r\n<html lang=\"${lang}\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>${escapeHtml(title)}</title>\r\n ${head}\r\n</head>\r\n<body${bodyAttrsStr}>\r\n <div id=\"app\">${content}</div>\r\n</body>\r\n</html>`;\r\n}\r\n\r\nexport default {\r\n renderToString,\r\n renderToHtml,\r\n};\r\n","/**\r\n * @lytjs/ssr - 虚拟列表组件\r\n *\r\n * 高性能大数据列表渲染\r\n */\r\n\r\nimport { defineComponent } from '@lytjs/component';\r\nimport { createVNode } from '@lytjs/vdom';\r\nimport { signal, computedSignal as computed } from '@lytjs/reactivity';\r\n\r\n/**\r\n * 虚拟列表组件\r\n */\r\nexport const VirtualList = defineComponent({\r\n name: 'LytVirtualList',\r\n\r\n props: {\r\n data: { type: Array, default: () => [] },\r\n itemHeight: { type: Number, default: 50 },\r\n height: { type: Number, default: 400 },\r\n buffer: { type: Number, default: 5 },\r\n class: { type: String, default: '' },\r\n },\r\n\r\n setup(props: any, { slots }: any) {\r\n // 滚动位置\r\n const scrollTop = signal(0);\r\n\r\n // 可视区域能显示的项数\r\n const visibleCount = computed(() => {\r\n return Math.ceil(props.height / props.itemHeight) + props.buffer * 2;\r\n });\r\n\r\n // 起始索引\r\n const startIndex = computed(() => {\r\n const start = Math.floor(scrollTop() / props.itemHeight);\r\n return Math.max(0, start - props.buffer);\r\n });\r\n\r\n // 结束索引\r\n const endIndex = computed(() => {\r\n return Math.min(props.data.length, startIndex() + visibleCount());\r\n });\r\n\r\n // 可视数据\r\n const visibleData = computed(() => {\r\n return props.data.slice(startIndex(), endIndex());\r\n });\r\n\r\n // 总高度\r\n const totalHeight = computed(() => {\r\n return props.data.length * props.itemHeight;\r\n });\r\n\r\n // 偏移量\r\n const offset = computed(() => {\r\n return startIndex() * props.itemHeight;\r\n });\r\n\r\n // 处理滚动\r\n const handleScroll = (e: Event) => {\r\n const target = e.target as HTMLElement;\r\n scrollTop.set(target.scrollTop);\r\n };\r\n\r\n // 生成类名\r\n const getListClass = () => {\r\n const classes = ['lyt-virtual-list'];\r\n if (props.class) classes.push(props.class);\r\n return classes.join(' ');\r\n };\r\n\r\n return () => {\r\n const items = visibleData().map((item: any, index: number) => {\r\n const actualIndex = startIndex() + index;\r\n return createVNode(\r\n 'div',\r\n {\r\n class: 'lyt-virtual-list__item',\r\n style: `height: ${props.itemHeight}px;`,\r\n 'data-index': actualIndex,\r\n },\r\n slots.default?.({ item, index: actualIndex })\r\n );\r\n });\r\n\r\n return createVNode(\r\n 'div',\r\n {\r\n class: getListClass(),\r\n style: `height: ${props.height}px; overflow-y: auto;`,\r\n onScroll: handleScroll,\r\n },\r\n [\r\n createVNode(\r\n 'div',\r\n {\r\n class: 'lyt-virtual-list__content',\r\n style: `height: ${totalHeight()}px; position: relative;`,\r\n },\r\n [\r\n createVNode(\r\n 'div',\r\n {\r\n class: 'lyt-virtual-list__visible',\r\n style: `position: absolute; top: ${offset()}px; left: 0; right: 0;`,\r\n },\r\n items\r\n ),\r\n ]\r\n ),\r\n ]\r\n );\r\n };\r\n },\r\n});\r\n\r\nexport default VirtualList;\r\n","/**\r\n * @lytjs/ssr - 流式服务端渲染\r\n *\r\n * 将 VNode 渲染为 ReadableStream,支持分块发送和 Suspense 边界\r\n */\r\n\r\nimport type { VNode } from '@lytjs/vdom';\r\nimport { isString, isNumber, isArray, isObject, isFunction } from '@lytjs/common-is';\r\nimport { renderToString } from './render';\r\n\r\n/** 流式渲染配置选项 */\r\nexport interface StreamRenderOptions {\r\n /** 每个分块的最大字节数,默认 4096 */\r\n chunkSize?: number;\r\n /** Shell 就绪回调(Suspense 边界之前的初始内容已发送) */\r\n onShellReady?: () => void;\r\n /** 错误回调 */\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/** 异步数据预取上下文 */\r\nexport interface DataPrefetchContext {\r\n /** 路由路径 */\r\n path?: string;\r\n /** 路由参数 */\r\n params?: Record<string, string>;\r\n /** 查询参数 */\r\n query?: Record<string, string>;\r\n}\r\n\r\n/** 异步数据预取结果 */\r\nexport interface PrefetchResult {\r\n /** 预取的数据 */\r\n data: Record<string, any>;\r\n /** 数据过期时间(毫秒) */\r\n ttl?: number;\r\n}\r\n\r\n/** 支持数据预取的组件接口 */\r\nexport interface PrefetchableComponent {\r\n /** 预取数据方法 */\r\n prefetch?: (context: DataPrefetchContext) => Promise<PrefetchResult>;\r\n}\r\n\r\n/** 流式渲染增强选项 */\r\nexport interface EnhancedStreamRenderOptions extends StreamRenderOptions {\r\n /** 数据预取上下文 */\r\n prefetchContext?: DataPrefetchContext;\r\n /** 数据预取完成回调 */\r\n onDataPrefetched?: (data: Record<string, any>) => void;\r\n /** 是否启用渐进式水合 */\r\n progressiveHydration?: boolean;\r\n}\r\n\r\n/** 默认分块大小 */\r\nconst DEFAULT_CHUNK_SIZE = 4096;\r\n\r\n/** Suspense 组件标记名称 */\r\nconst SUSPENSE_TYPE = 'Suspense';\r\n\r\n/**\r\n * 判断 VNode 是否为 Suspense 边界\r\n */\r\nfunction isSuspenseVNode(vnode: VNode): boolean {\r\n return (\r\n isObject(vnode) &&\r\n ((typeof vnode.type === 'object' && vnode.type !== null &&\r\n '__suspense' in (vnode.type as Record<string, unknown>)) ||\r\n (isString(vnode.type) && vnode.type === SUSPENSE_TYPE))\r\n );\r\n}\r\n\r\n/**\r\n * 从 VNode 树中收集所有组件边界,用于分块\r\n *\r\n * @description\r\n * 遍历 VNode 树,在每个元素组件边界处拆分,\r\n * 返回 HTML 片段数组。遇到 Suspense 边界时标记 shell 结束位置。\r\n */\r\nfunction collectChunks(\r\n vnode: VNode,\r\n suspenseBoundaryIndex: number[] = []\r\n): string[] {\r\n const chunks: string[] = [];\r\n\r\n // 处理 null/undefined\r\n if (vnode == null) {\r\n return chunks;\r\n }\r\n\r\n // 处理字符串和数字\r\n if (isString(vnode) || isNumber(vnode)) {\r\n chunks.push(renderToString(vnode));\r\n return chunks;\r\n }\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n for (const child of vnode) {\r\n chunks.push(...collectChunks(child as VNode, suspenseBoundaryIndex));\r\n }\r\n return chunks;\r\n }\r\n\r\n // 处理非对象\r\n if (!isObject(vnode)) {\r\n return chunks;\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 检查是否为 Suspense 边界\r\n if (isSuspenseVNode(node)) {\r\n suspenseBoundaryIndex.push(chunks.length);\r\n }\r\n\r\n // 处理文本节点\r\n if (node.type === 'text' || typeof node.type === 'symbol') {\r\n chunks.push(renderToString(node));\r\n return chunks;\r\n }\r\n\r\n // 处理组件类型\r\n if (isFunction(node.type)) {\r\n chunks.push(renderToString(node));\r\n return chunks;\r\n }\r\n\r\n // 处理元素类型\r\n if (isString(node.type)) {\r\n chunks.push(renderToString(node));\r\n return chunks;\r\n }\r\n\r\n return chunks;\r\n}\r\n\r\n/**\r\n * 将 HTML 字符串按指定大小分块\r\n *\r\n * @param html - 完整的 HTML 字符串\r\n * @param chunkSize - 每个分块的最大字节数\r\n * @returns 分块后的字符串数组\r\n */\r\nfunction splitIntoByteChunks(html: string, chunkSize: number): string[] {\r\n const encoder = new TextEncoder();\r\n const chunks: string[] = [];\r\n let remaining = html;\r\n\r\n while (remaining.length > 0) {\r\n // 计算当前分块的字节数\r\n const encoded = encoder.encode(remaining);\r\n if (encoded.length <= chunkSize) {\r\n chunks.push(remaining);\r\n break;\r\n }\r\n\r\n // 按字符逐步逼近目标字节数\r\n let cutIndex = 0;\r\n let byteCount = 0;\r\n for (let i = 0; i < remaining.length; i++) {\r\n byteCount += encoder.encode(remaining[i]).length;\r\n if (byteCount > chunkSize) {\r\n cutIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n // 防止无限循环\r\n if (cutIndex === 0) {\r\n cutIndex = 1;\r\n }\r\n\r\n chunks.push(remaining.slice(0, cutIndex));\r\n remaining = remaining.slice(cutIndex);\r\n }\r\n\r\n return chunks;\r\n}\r\n\r\n/**\r\n * 将 VNode 渲染为 ReadableStream(流式服务端渲染)\r\n *\r\n * @description\r\n * 将 VNode 树渲染为 HTML 并通过 ReadableStream 分块发送。\r\n * 支持以下特性:\r\n * - 按组件边界拆分 HTML 分块\r\n * - 支持 Suspense 边界(先发送 shell,再发送异步内容)\r\n * - 使用 TextEncoder 编码为 Uint8Array\r\n * - 可配置分块大小和回调\r\n *\r\n * @param vnode - 要渲染的 VNode\r\n * @param options - 流式渲染配置选项\r\n * @returns ReadableStream<Uint8Array>\r\n *\r\n * @example\r\n * ```typescript\r\n * const stream = renderToStream(vnode, {\r\n * chunkSize: 2048,\r\n * onShellReady: () => console.log('Shell 已发送'),\r\n * onError: (err) => console.error(err),\r\n * });\r\n *\r\n * for await (const chunk of stream) {\r\n * response.write(chunk);\r\n * }\r\n * ```\r\n */\r\nexport function renderToStream(\r\n vnode: VNode,\r\n options?: StreamRenderOptions\r\n): ReadableStream<Uint8Array> {\r\n const {\r\n chunkSize = DEFAULT_CHUNK_SIZE,\r\n onShellReady,\r\n onError,\r\n } = options || {};\r\n\r\n const encoder = new TextEncoder();\r\n\r\n return new ReadableStream<Uint8Array>({\r\n start(controller) {\r\n try {\r\n // 收集组件边界分块\r\n const suspenseBoundaryIndex: number[] = [];\r\n const chunks = collectChunks(vnode, suspenseBoundaryIndex);\r\n const fullHtml = chunks.join('');\r\n\r\n // 如果存在 Suspense 边界,先发送 shell 部分\r\n if (suspenseBoundaryIndex.length > 0) {\r\n const shellBoundary = suspenseBoundaryIndex[0];\r\n const shellChunks = chunks.slice(0, shellBoundary);\r\n const shellHtml = shellChunks.join('');\r\n const byteChunks = splitIntoByteChunks(shellHtml, chunkSize);\r\n\r\n // 发送 shell 分块\r\n for (const chunk of byteChunks) {\r\n controller.enqueue(encoder.encode(chunk));\r\n }\r\n\r\n // 通知 shell 就绪\r\n onShellReady?.();\r\n\r\n // 发送剩余内容\r\n const remainingChunks = chunks.slice(shellBoundary);\r\n const remainingHtml = remainingChunks.join('');\r\n const remainingByteChunks = splitIntoByteChunks(remainingHtml, chunkSize);\r\n\r\n for (const chunk of remainingByteChunks) {\r\n controller.enqueue(encoder.encode(chunk));\r\n }\r\n } else {\r\n // 无 Suspense 边界,直接分块发送\r\n const byteChunks = splitIntoByteChunks(fullHtml, chunkSize);\r\n for (const chunk of byteChunks) {\r\n controller.enqueue(encoder.encode(chunk));\r\n }\r\n }\r\n\r\n controller.close();\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n onError?.(error);\r\n controller.error(error);\r\n }\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * 将 VNode 渲染为异步 ReadableStream(支持异步组件和数据预取)\r\n *\r\n * @description\r\n * 与 renderToStream 类似,但支持异步组件和数据预取。\r\n * 遇到返回 Promise 的组件时先发送占位内容,等 Promise 解析后再发送实际内容。\r\n *\r\n * @param vnode - 要渲染的 VNode\r\n * @param options - 流式渲染配置选项\r\n * @returns ReadableStream<Uint8Array>\r\n */\r\nexport function renderToStreamAsync(\r\n vnode: VNode,\r\n options?: EnhancedStreamRenderOptions\r\n): ReadableStream<Uint8Array> {\r\n const {\r\n chunkSize = DEFAULT_CHUNK_SIZE,\r\n onShellReady,\r\n onError,\r\n prefetchContext,\r\n onDataPrefetched,\r\n } = options || {};\r\n\r\n const encoder = new TextEncoder();\r\n\r\n return new ReadableStream<Uint8Array>({\r\n async start(controller) {\r\n try {\r\n // 首先进行数据预取\r\n const prefetchData = await collectAndPrefetchData(vnode, prefetchContext);\r\n if (Object.keys(prefetchData).length > 0) {\r\n onDataPrefetched?.(prefetchData);\r\n }\r\n\r\n // 渲染 HTML\r\n const html = await renderToStringAsync(vnode, prefetchData);\r\n const byteChunks = splitIntoByteChunks(html, chunkSize);\r\n\r\n onShellReady?.();\r\n\r\n for (const chunk of byteChunks) {\r\n controller.enqueue(encoder.encode(chunk));\r\n }\r\n\r\n controller.close();\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n onError?.(error);\r\n controller.error(error);\r\n }\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * 收集并预取 VNode 树中的所有数据\r\n *\r\n * @param vnode - VNode 树\r\n * @param context - 数据预取上下文\r\n * @returns 预取的数据对象\r\n */\r\nasync function collectAndPrefetchData(\r\n vnode: VNode | VNode[] | string | number | null | undefined,\r\n context?: DataPrefetchContext\r\n): Promise<Record<string, any>> {\r\n const result: Record<string, any> = {};\r\n\r\n // 处理 null/undefined\r\n if (vnode === null || vnode === undefined) {\r\n return result;\r\n }\r\n\r\n // 处理字符串/数字\r\n if (isString(vnode) || isNumber(vnode)) {\r\n return result;\r\n }\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n const results = await Promise.all(\r\n vnode.map(child => collectAndPrefetchData(child as VNode, context))\r\n );\r\n // 合并所有结果\r\n for (const data of results) {\r\n Object.assign(result, data);\r\n }\r\n return result;\r\n }\r\n\r\n // 处理非对象\r\n if (!isObject(vnode)) {\r\n return result;\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 处理文本节点\r\n if (node.type === 'text' || typeof node.type === 'symbol') {\r\n return result;\r\n }\r\n\r\n // 处理组件类型 - 检查是否有 prefetch 方法\r\n if (isFunction(node.type)) {\r\n const component = node.type as unknown as PrefetchableComponent;\r\n if (component.prefetch && context) {\r\n try {\r\n const prefetchResult = await component.prefetch(context);\r\n Object.assign(result, prefetchResult.data);\r\n } catch (e) {\r\n // 预取失败不阻止渲染\r\n console.warn('Data prefetch failed:', e);\r\n }\r\n }\r\n // 继续处理子节点\r\n if (node.children) {\r\n const childData = await collectAndPrefetchData(node.children as unknown as VNode, context);\r\n Object.assign(result, childData);\r\n }\r\n return result;\r\n }\r\n\r\n // 处理元素类型\r\n if (isString(node.type)) {\r\n if (node.children) {\r\n const childData = await collectAndPrefetchData(node.children as unknown as VNode, context);\r\n Object.assign(result, childData);\r\n }\r\n return result;\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * 异步渲染 VNode 为 HTML 字符串(支持预取数据)\r\n *\r\n * @description\r\n * 递归渲染 VNode 树,遇到返回 Promise 的组件时等待解析。\r\n * 支持使用预取的数据进行渲染。\r\n *\r\n * @param vnode - VNode 树\r\n * @param prefetchData - 预取的数据\r\n * @returns HTML 字符串\r\n */\r\nasync function renderToStringAsync(\r\n vnode: VNode | VNode[] | string | number | null | undefined,\r\n prefetchData?: Record<string, any>\r\n): Promise<string> {\r\n // 处理 null/undefined\r\n if (vnode === null || vnode === undefined) {\r\n return '';\r\n }\r\n\r\n // 处理字符串\r\n if (isString(vnode)) {\r\n return renderToString(vnode);\r\n }\r\n\r\n // 处理数字\r\n if (isNumber(vnode)) {\r\n return String(vnode);\r\n }\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n const results = await Promise.all(\r\n vnode.map(child => renderToStringAsync(child as VNode, prefetchData))\r\n );\r\n return results.join('');\r\n }\r\n\r\n // 处理非对象\r\n if (!isObject(vnode)) {\r\n return '';\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 处理文本节点\r\n if (node.type === 'text' || typeof node.type === 'symbol') {\r\n return renderToString(node);\r\n }\r\n\r\n // 处理组件类型(可能返回 Promise)\r\n if (isFunction(node.type)) {\r\n return renderToString(node);\r\n }\r\n\r\n // 处理元素类型\r\n if (isString(node.type)) {\r\n return renderToString(node);\r\n }\r\n\r\n return '';\r\n}\r\n\r\n/**\r\n * 增强型流式渲染(包含数据预取和渐进式水合)\r\n *\r\n * @description\r\n * 完整的流式渲染解决方案,包含数据预取、渐进式水合等高级特性。\r\n *\r\n * @param vnode - 要渲染的 VNode\r\n * @param options - 增强型流式渲染配置\r\n * @returns Promise<{ stream: ReadableStream<Uint8Array>; dehydratedState: Record<string, any> }>\r\n */\r\nexport async function renderToStreamEnhanced(\r\n vnode: VNode,\r\n options?: EnhancedStreamRenderOptions\r\n): Promise<{\r\n stream: ReadableStream<Uint8Array>;\r\n dehydratedState: Record<string, any>;\r\n}> {\r\n const { prefetchContext, onDataPrefetched } = options || {};\r\n\r\n // 首先进行数据预取\r\n const prefetchData = await collectAndPrefetchData(vnode, prefetchContext);\r\n if (Object.keys(prefetchData).length > 0 && onDataPrefetched) {\r\n onDataPrefetched(prefetchData);\r\n }\r\n\r\n // 创建脱水状态\r\n const dehydratedState = {\r\n prefetchData,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // 创建流式渲染\r\n const stream = renderToStreamAsync(vnode, {\r\n ...options,\r\n onDataPrefetched: undefined, // 避免重复调用\r\n });\r\n\r\n return {\r\n stream,\r\n dehydratedState,\r\n };\r\n}\r\n","/**\r\n * @lytjs/ssr - 静态站点生成(SSG)\r\n *\r\n * 预渲染页面配置为静态 HTML 文件\r\n */\r\n\r\nimport type { VNode } from '@lytjs/vdom';\r\nimport { isString } from '@lytjs/common-is';\r\nimport { renderToHtml } from './render';\r\nimport { promises as fs } from 'fs';\r\nimport { join, dirname } from 'path';\r\n\r\n/** SSG 页面配置 */\r\nexport interface SSGPage {\r\n /** 页面路径,如 '/' 或 '/about' */\r\n path: string;\r\n /** 页面组件 VNode */\r\n component: VNode;\r\n /** 可选布局组件 */\r\n layout?: VNode;\r\n /** 页面头部信息 */\r\n head?: {\r\n /** 页面标题 */\r\n title?: string;\r\n /** 元信息键值对 */\r\n meta?: Record<string, string>;\r\n };\r\n /** 额外的脚本标签 */\r\n scripts?: string[];\r\n /** 额外的样式标签 */\r\n styles?: string[];\r\n}\r\n\r\n/** SSG 生成选项 */\r\nexport interface SSGOptions {\r\n /** 站点基础 URL,默认 '/' */\r\n baseUrl?: string;\r\n /** 输出目录,默认 'dist' */\r\n outDir?: string;\r\n /** 默认页面标题 */\r\n defaultTitle?: string;\r\n /** 默认语言 */\r\n lang?: string;\r\n /** 是否生成 sitemap */\r\n generateSitemap?: boolean;\r\n /** 站点名称(用于 sitemap) */\r\n siteName?: string;\r\n /** 是否使用哈希路由 */\r\n hashMode?: boolean;\r\n /** 全局额外脚本 */\r\n globalScripts?: string[];\r\n /** 全局额外样式 */\r\n globalStyles?: string[];\r\n}\r\n\r\n/** 默认 SSG 选项 */\r\nconst DEFAULT_SSG_OPTIONS: Required<SSGOptions> = {\r\n baseUrl: '/',\r\n outDir: 'dist',\r\n defaultTitle: 'LytJS App',\r\n lang: 'zh-CN',\r\n generateSitemap: false,\r\n siteName: 'LytJS Site',\r\n hashMode: false,\r\n globalScripts: [],\r\n globalStyles: [],\r\n};\r\n\r\n/**\r\n * 规范化页面路径\r\n *\r\n * @description\r\n * 确保路径以 / 开头,去除末尾的 /\r\n *\r\n * @param path - 原始路径\r\n * @returns 规范化后的路径\r\n */\r\nfunction normalizePath(path: string): string {\r\n // 确保路径以 / 开头\r\n let normalized = path.startsWith('/') ? path : `/${path}`;\r\n // 去除末尾的 /(根路径除外)\r\n if (normalized.length > 1 && normalized.endsWith('/')) {\r\n normalized = normalized.slice(0, -1);\r\n }\r\n return normalized;\r\n}\r\n\r\n/**\r\n * 将路径转换为文件路径\r\n *\r\n * @description\r\n * 将 URL 路径转换为文件系统路径,\r\n * 例如 '/about' -> '/about/index.html','/' -> '/index.html'\r\n *\r\n * @param path - 规范化后的路径\r\n * @returns 文件路径\r\n */\r\nfunction pathToFilePath(path: string): string {\r\n if (path === '/') {\r\n return '/index.html';\r\n }\r\n return `${path}/index.html`;\r\n}\r\n\r\n/**\r\n * 生成 meta 标签 HTML 字符串\r\n *\r\n * @param meta - 元信息键值对\r\n * @returns meta 标签 HTML 字符串\r\n */\r\nfunction renderMetaTags(meta: Record<string, string>): string {\r\n return Object.entries(meta)\r\n .map(([name, content]) => `<meta name=\"${name}\" content=\"${content}\">`)\r\n .join('\\n ');\r\n}\r\n\r\n/**\r\n * 渲染单个页面为完整 HTML\r\n *\r\n * @description\r\n * 将页面组件和可选布局组合渲染为完整的 HTML 文档字符串。\r\n * 如果提供了布局,组件内容会被包裹在布局中。\r\n *\r\n * @param page - 页面配置\r\n * @param options - SSG 选项\r\n * @returns 完整的 HTML 字符串\r\n */\r\nfunction renderPage(page: SSGPage, options: Required<SSGOptions>): string {\r\n const { component, layout, head, scripts, styles } = page;\r\n const title = head?.title || options.defaultTitle;\r\n\r\n // 构建 head 中的额外内容\r\n let extraHead = '';\r\n if (head?.meta) {\r\n extraHead = renderMetaTags(head.meta);\r\n }\r\n\r\n // 合并全局和页面的样式\r\n const allStyles = [...(options.globalStyles || []), ...(styles || [])];\r\n const allScripts = [...(options.globalScripts || []), ...(scripts || [])];\r\n\r\n // 添加样式标签\r\n if (allStyles.length > 0) {\r\n extraHead += '\\n ' + allStyles.join('\\n ');\r\n }\r\n\r\n // 添加脚本标签到 head 结束之前\r\n if (allScripts.length > 0) {\r\n extraHead += '\\n ' + allScripts.join('\\n ');\r\n }\r\n\r\n // 如果有布局,将组件包裹在布局中\r\n const content = layout\r\n ? renderToHtml(component, { title, lang: options.lang, head: extraHead })\r\n : renderToHtml(component, { title, lang: options.lang, head: extraHead });\r\n\r\n return content;\r\n}\r\n\r\n/**\r\n * 生成 sitemap.xml\r\n *\r\n * @param pages - 页面配置数组\r\n * @param options - SSG 选项\r\n * @returns sitemap XML 字符串\r\n */\r\nfunction generateSitemapXml(\r\n pages: SSGPage[],\r\n options: Required<SSGOptions>\r\n): string {\r\n const baseUrl = options.baseUrl.endsWith('/') \r\n ? options.baseUrl.slice(0, -1) \r\n : options.baseUrl;\r\n\r\n const urls = pages.map(page => {\r\n const path = normalizePath(page.path);\r\n const fullUrl = options.hashMode \r\n ? `${baseUrl}/#${path}` \r\n : `${baseUrl}${path}`;\r\n const lastmod = new Date().toISOString().split('T')[0];\r\n \r\n return ` <url>\r\n <loc>${fullUrl}</loc>\r\n <lastmod>${lastmod}</lastmod>\r\n <changefreq>weekly</changefreq>\r\n <priority>0.8</priority>\r\n </url>`;\r\n }).join('\\n');\r\n\r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`;\r\n}\r\n\r\n/**\r\n * 将生成的 HTML 写入文件系统\r\n *\r\n * @description\r\n * 将 generateStaticPages 生成的结果写入到指定的输出目录。\r\n * 会自动创建所需的目录结构。\r\n *\r\n * @param pages - 页面配置数组\r\n * @param options - SSG 选项\r\n * @returns Promise<void>\r\n *\r\n * @example\r\n * ```typescript\r\n * await writeStaticFiles(pages, { outDir: 'build' });\r\n * ```\r\n */\r\nexport async function writeStaticFiles(\r\n pages: SSGPage[],\r\n options?: SSGOptions\r\n): Promise<void> {\r\n const resolvedOptions = { ...DEFAULT_SSG_OPTIONS, ...options };\r\n const { outDir, generateSitemap } = resolvedOptions;\r\n\r\n // 验证页面配置\r\n const errors = validatePages(pages);\r\n if (errors.length > 0) {\r\n throw new Error(`页面配置验证失败:\\n${errors.join('\\n')}`);\r\n }\r\n\r\n // 生成静态页面\r\n const staticPages = generateStaticPages(pages, resolvedOptions);\r\n\r\n // 写入每个页面\r\n for (const [filePath, html] of staticPages) {\r\n const fullPath = join(outDir, filePath);\r\n const dir = dirname(fullPath);\r\n \r\n // 创建目录(如果不存在)\r\n await fs.mkdir(dir, { recursive: true });\r\n \r\n // 写入文件\r\n await fs.writeFile(fullPath, html, 'utf-8');\r\n }\r\n\r\n // 如果需要,生成 sitemap\r\n if (generateSitemap) {\r\n const sitemapContent = generateSitemapXml(pages, resolvedOptions);\r\n const sitemapPath = join(outDir, 'sitemap.xml');\r\n await fs.writeFile(sitemapPath, sitemapContent, 'utf-8');\r\n }\r\n}\r\n\r\n/**\r\n * 预渲染页面配置数组为静态 HTML\r\n *\r\n * @description\r\n * 接受页面配置数组,为每个页面生成完整的 HTML 内容。\r\n * 返回一个 Map,键为文件路径,值为 HTML 内容。\r\n *\r\n * @param pages - 页面配置数组\r\n * @param options - SSG 生成选项\r\n * @returns Map<string, string> 文件路径 -> HTML 内容\r\n *\r\n * @example\r\n * ```typescript\r\n * const pages: SSGPage[] = [\r\n * {\r\n * path: '/',\r\n * component: h('div', {}, 'Home'),\r\n * head: { title: '首页', meta: { description: '欢迎' } },\r\n * },\r\n * {\r\n * path: '/about',\r\n * component: h('div', {}, 'About'),\r\n * },\r\n * ];\r\n *\r\n * const results = generateStaticPages(pages, {\r\n * baseUrl: 'https://example.com',\r\n * defaultTitle: 'My Site',\r\n * });\r\n *\r\n * for (const [filePath, html] of results) {\r\n * console.log(filePath, html);\r\n * }\r\n * ```\r\n */\r\nexport function generateStaticPages(\r\n pages: SSGPage[],\r\n options?: SSGOptions\r\n): Map<string, string> {\r\n const resolvedOptions = { ...DEFAULT_SSG_OPTIONS, ...options };\r\n const results = new Map<string, string>();\r\n\r\n for (const page of pages) {\r\n const normalizedPath = normalizePath(page.path);\r\n const filePath = pathToFilePath(normalizedPath);\r\n const html = renderPage(page, resolvedOptions);\r\n results.set(filePath, html);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * 生成页面路由清单\r\n *\r\n * @description\r\n * 根据页面配置生成一个 JSON 格式的路由清单,\r\n * 可用于客户端路由注册或构建分析。\r\n *\r\n * @param pages - 页面配置数组\r\n * @param baseUrl - 站点基础 URL\r\n * @returns 路由信息数组\r\n */\r\nexport function generateRouteManifest(\r\n pages: SSGPage[],\r\n baseUrl: string = '/'\r\n): Array<{ path: string; filePath: string; title?: string }> {\r\n return pages.map(page => {\r\n const normalizedPath = normalizePath(page.path);\r\n const filePath = pathToFilePath(normalizedPath);\r\n return {\r\n path: `${baseUrl}${normalizedPath}`,\r\n filePath,\r\n title: page.head?.title,\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * 验证页面配置数组的合法性\r\n *\r\n * @description\r\n * 检查每个页面配置是否包含必要的字段(path 和 component),\r\n * 以及路径是否合法。返回错误信息数组。\r\n *\r\n * @param pages - 页面配置数组\r\n * @returns 错误信息数组,空数组表示全部合法\r\n */\r\nexport function validatePages(pages: SSGPage[]): string[] {\r\n const errors: string[] = [];\r\n\r\n for (let i = 0; i < pages.length; i++) {\r\n const page = pages[i];\r\n if (!page) {\r\n errors.push(`页面 ${i}: 无效的页面配置`);\r\n continue;\r\n }\r\n\r\n const pagePath = page.path;\r\n\r\n // 检查 path\r\n if (!pagePath || !isString(pagePath)) {\r\n errors.push(`页面 ${i}: path 必须是非空字符串`);\r\n continue;\r\n }\r\n\r\n // 检查 component\r\n if (!page.component) {\r\n errors.push(`页面 \"${pagePath}\": component 不能为空`);\r\n }\r\n\r\n // 检查路径合法性\r\n if (isString(pagePath) && !pagePath.startsWith('/')) {\r\n errors.push(`页面 \"${pagePath}\": path 必须以 / 开头`);\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n","/**\r\n * @lytjs/ssr - 组件级水合提示\r\n *\r\n * 提供水合标记、策略检测和状态序列化等辅助函数,\r\n * 用于 SSR 输出中嵌入客户端水合所需的信息\r\n */\r\n\r\nimport type { VNode, VNodeChildren } from '@lytjs/vdom';\r\nimport { isString, isNumber, isArray, isObject, isFunction, isNullish } from '@lytjs/common-is';\r\n\r\n/** 水合策略类型 */\r\nexport type HydrationStrategy = 'lazy' | 'eager' | 'idle';\r\n\r\n/** 水合提示信息 */\r\nexport interface HydrationHints {\r\n /** 组件唯一标识 */\r\n componentId: string;\r\n /** 水合策略 */\r\n strategy: HydrationStrategy;\r\n /** 组件 props 快照 */\r\n props: Record<string, unknown>;\r\n}\r\n\r\n/** 水合状态数据结构 */\r\nexport interface HydrationState {\r\n /** 组件水合提示列表 */\r\n hints: HydrationHints[];\r\n /** 全局初始状态 */\r\n initialState?: Record<string, unknown>;\r\n}\r\n\r\n/** 水合标记属性名 */\r\nconst HYDRATE_ATTR = 'data-hydrate';\r\n/** 水合策略属性名 */\r\nconst HYDRATE_STRATEGY_ATTR = 'data-hydrate-strategy';\r\n/** 脱水状态 script 标记 */\r\nconst DEHYDRATED_STATE_ID = '__LYT_DEHYDRATED_STATE__';\r\n\r\n/** 组件 ID 计数器 */\r\nlet componentIdCounter = 0;\r\n\r\n/**\r\n * 生成唯一的组件 ID\r\n *\r\n * @returns 唯一标识字符串\r\n */\r\nfunction generateComponentId(): string {\r\n componentIdCounter++;\r\n return `lyt-hydrate-${componentIdCounter}`;\r\n}\r\n\r\n/**\r\n * 重置组件 ID 计数器(仅用于测试)\r\n */\r\nexport function resetComponentIdCounter(): void {\r\n componentIdCounter = 0;\r\n}\r\n\r\n/**\r\n * 判断 VNode 是否为元素类型\r\n */\r\nfunction isElementVNode(vnode: VNode): boolean {\r\n return isObject(vnode) && isString((vnode as VNode).type);\r\n}\r\n\r\n/**\r\n * 判断 VNode 是否为组件类型\r\n */\r\nfunction isComponentVNode(vnode: VNode): boolean {\r\n return isObject(vnode) && isFunction((vnode as VNode).type);\r\n}\r\n\r\n/**\r\n * 获取 VNode 的 props(安全访问)\r\n */\r\nfunction getVNodeProps(vnode: VNode): Record<string, unknown> {\r\n if (isObject(vnode) && isObject((vnode as VNode).props)) {\r\n return (vnode as VNode).props as Record<string, unknown>;\r\n }\r\n return {};\r\n}\r\n\r\n/**\r\n * 获取 VNode 的 children(安全访问)\r\n */\r\nfunction getVNodeChildren(vnode: VNode): VNode[] | string | number | null {\r\n if (isObject(vnode)) {\r\n return (vnode as VNode).children as VNode[] | string | number | null;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * 为 VNode 树添加水合标记\r\n *\r\n * @description\r\n * 递归遍历 VNode 树,为每个元素节点添加 data-hydrate 属性,\r\n * 用于客户端水合时识别对应的 SSR 输出节点。\r\n * 同时根据 props 中的 hydrateStrategy 设置 data-hydrate-strategy 属性。\r\n *\r\n * @param vnode - 原始 VNode\r\n * @returns 添加了水合标记的新 VNode(浅拷贝)\r\n *\r\n * @example\r\n * ```typescript\r\n * const marked = createHydrationMarkers(vnode);\r\n * // marked 的每个元素节点都带有 data-hydrate=\"lyt-hydrate-1\" 等属性\r\n * ```\r\n */\r\nexport function createHydrationMarkers(vnode: VNode): VNode {\r\n // 非对象类型直接返回\r\n if (!isObject(vnode)) {\r\n return vnode;\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n return vnode.map(child =>\r\n createHydrationMarkers(child as VNode)\r\n ) as unknown as VNode;\r\n }\r\n\r\n // 处理元素节点 - 添加水合标记\r\n if (isElementVNode(node)) {\r\n const id = generateComponentId();\r\n const props = { ...getVNodeProps(node) };\r\n props[HYDRATE_ATTR] = id;\r\n\r\n // 检查是否有水合策略\r\n const strategy = props['hydrateStrategy'] as HydrationStrategy | undefined;\r\n if (strategy && isValidStrategy(strategy)) {\r\n props[HYDRATE_STRATEGY_ATTR] = strategy;\r\n }\r\n\r\n // 递归处理子节点\r\n const children = getVNodeChildren(node);\r\n let processedChildren: VNodeChildren = children;\r\n if (children !== null && !isString(children) && !isNumber(children)) {\r\n if (isArray(children)) {\r\n processedChildren = children.map(child =>\r\n createHydrationMarkers(child as VNode)\r\n );\r\n } else if (isObject(children)) {\r\n processedChildren = [createHydrationMarkers(children as VNode)];\r\n }\r\n }\r\n\r\n return { ...node, props, children: processedChildren } as VNode;\r\n }\r\n\r\n // 处理组件节点 - 递归但不添加标记\r\n if (isComponentVNode(node)) {\r\n const children = getVNodeChildren(node);\r\n if (children !== null && !isString(children) && !isNumber(children)) {\r\n if (isArray(children)) {\r\n return {\r\n ...node,\r\n children: children.map(child =>\r\n createHydrationMarkers(child as VNode)\r\n ),\r\n } as VNode;\r\n } else if (isObject(children)) {\r\n return {\r\n ...node,\r\n children: [createHydrationMarkers(children as VNode)],\r\n } as VNode;\r\n }\r\n }\r\n return node;\r\n }\r\n\r\n return node;\r\n}\r\n\r\n/**\r\n * 验证水合策略是否合法\r\n */\r\nfunction isValidStrategy(strategy: string): strategy is HydrationStrategy {\r\n return strategy === 'lazy' || strategy === 'eager' || strategy === 'idle';\r\n}\r\n\r\n/**\r\n * 获取组件的水合策略\r\n *\r\n * @description\r\n * 从 VNode 的 props 中读取 hydrateStrategy 字段,\r\n * 返回对应的水合策略。如果未设置,默认返回 'eager'。\r\n *\r\n * @param vnode - 目标 VNode\r\n * @returns 水合策略(lazy / eager / idle)\r\n *\r\n * @example\r\n * ```typescript\r\n * const strategy = getHydrationStrategy(vnode);\r\n * // 'eager' | 'lazy' | 'idle'\r\n * ```\r\n */\r\nexport function getHydrationStrategy(vnode: VNode): HydrationStrategy {\r\n if (!isObject(vnode)) {\r\n return 'eager';\r\n }\r\n\r\n const props = getVNodeProps(vnode as VNode);\r\n const strategy = props['hydrateStrategy'];\r\n\r\n if (isString(strategy) && isValidStrategy(strategy)) {\r\n return strategy;\r\n }\r\n\r\n return 'eager';\r\n}\r\n\r\n/**\r\n * 从 VNode 树中收集所有水合提示\r\n *\r\n * @description\r\n * 遍历 VNode 树,收集所有组件的水合信息,\r\n * 包括组件 ID、水合策略和 props 快照。\r\n */\r\nfunction collectHydrationHints(\r\n vnode: VNode,\r\n hints: HydrationHints[] = []\r\n): HydrationHints[] {\r\n if (!isObject(vnode)) {\r\n return hints;\r\n }\r\n\r\n const node = vnode as VNode;\r\n\r\n // 处理数组\r\n if (isArray(vnode)) {\r\n for (const child of vnode) {\r\n collectHydrationHints(child as VNode, hints);\r\n }\r\n return hints;\r\n }\r\n\r\n // 元素节点 - 收集提示\r\n if (isElementVNode(node)) {\r\n const props = getVNodeProps(node);\r\n const hydrateId = props[HYDRATE_ATTR];\r\n\r\n if (isString(hydrateId)) {\r\n // 过滤掉内部属性\r\n const cleanProps: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(props)) {\r\n if (!key.startsWith('data-') && key !== 'key' && key !== 'ref') {\r\n cleanProps[key] = value;\r\n }\r\n }\r\n\r\n hints.push({\r\n componentId: hydrateId,\r\n strategy: getHydrationStrategy(node),\r\n props: cleanProps,\r\n });\r\n }\r\n\r\n // 递归处理子节点\r\n const children = getVNodeChildren(node);\r\n if (children !== null && !isString(children) && !isNumber(children)) {\r\n if (isArray(children)) {\r\n for (const child of children) {\r\n collectHydrationHints(child as VNode, hints);\r\n }\r\n } else if (isObject(children)) {\r\n collectHydrationHints(children as VNode, hints);\r\n }\r\n }\r\n }\r\n\r\n return hints;\r\n}\r\n\r\n/**\r\n * 序列化客户端水合所需的初始状态\r\n *\r\n * @description\r\n * 将任意状态对象序列化为可安全嵌入 HTML 的 JSON 字符串。\r\n * 处理特殊值(undefined、函数、Symbol 等)以确保 JSON 安全。\r\n *\r\n * @param state - 要序列化的状态对象\r\n * @returns JSON 字符串\r\n *\r\n * @example\r\n * ```typescript\r\n * const serialized = serializeHydrationState({\r\n * user: { name: 'Alice', age: 30 },\r\n * items: [1, 2, 3],\r\n * });\r\n * // '{\"user\":{\"name\":\"Alice\",\"age\":30},\"items\":[1,2,3]}'\r\n * ```\r\n */\r\nexport function serializeHydrationState(state: unknown): string {\r\n if (isNullish(state)) {\r\n return '{}';\r\n }\r\n\r\n // 使用 JSON.stringify 并处理特殊值\r\n return JSON.stringify(state, (_, value) => {\r\n // 过滤掉 undefined\r\n if (typeof value === 'undefined') {\r\n return null;\r\n }\r\n // 过滤掉函数\r\n if (typeof value === 'function') {\r\n return null;\r\n }\r\n // 过滤掉 Symbol\r\n if (typeof value === 'symbol') {\r\n return null;\r\n }\r\n return value;\r\n });\r\n}\r\n\r\n/**\r\n * 创建脱水状态(SSR 时序列化到 HTML 中的状态)\r\n *\r\n * @description\r\n * 从 VNode 树中提取水合所需的信息,生成一段可嵌入 HTML 的 script 标签内容。\r\n * 客户端加载时读取此状态进行水合。\r\n *\r\n * @param vnode - VNode 节点\r\n * @param initialState - 可选的全局初始状态\r\n * @returns 可嵌入 HTML 的 script 标签字符串\r\n *\r\n * @example\r\n * ```typescript\r\n * const script = createDehydratedState(vnode, {\r\n * user: { name: 'Alice' },\r\n * });\r\n * // <script id=\"__LYT_DEHYDRATED_STATE__\" type=\"application/json\">...</script>\r\n * ```\r\n */\r\nexport function createDehydratedState(\r\n vnode: VNode,\r\n initialState?: Record<string, unknown>\r\n): string {\r\n // 重置计数器以确保一致性\r\n resetComponentIdCounter();\r\n\r\n // 先为 VNode 树添加水合标记,再收集提示\r\n const markedVNode = createHydrationMarkers(vnode);\r\n const hints = collectHydrationHints(markedVNode);\r\n\r\n // 构建完整的水合状态\r\n const hydrationState: HydrationState = {\r\n hints,\r\n initialState,\r\n };\r\n\r\n // 序列化为 JSON\r\n const json = serializeHydrationState(hydrationState);\r\n\r\n // 转义 script 标签中的特殊字符\r\n const safeJson = json\r\n .replace(/</g, '\\\\u003c')\r\n .replace(/>/g, '\\\\u003e')\r\n .replace(/\\/script/gi, '\\\\/script');\r\n\r\n return `<script id=\"${DEHYDRATED_STATE_ID}\" type=\"application/json\">${safeJson}</script>`;\r\n}\r\n"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@lytjs/ssr",
3
+ "version": "6.0.0",
4
+ "description": "LytJS Server-Side Rendering support",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "test": "vitest run",
23
+ "type-check": "tsc --noEmit",
24
+ "clean": "rm -rf dist"
25
+ },
26
+ "dependencies": {
27
+ "@lytjs/common-is": "^6.0.0",
28
+ "@lytjs/common-env": "^6.0.0",
29
+ "@lytjs/common-dom": "^6.0.0",
30
+ "@lytjs/reactivity": "^6.0.0",
31
+ "@lytjs/component": "^6.0.0",
32
+ "@lytjs/vdom": "^6.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "tsup": "^8.0.0",
36
+ "typescript": "^5.4.0",
37
+ "vitest": "^3.0.0"
38
+ },
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://gitee.com/lytjs/lytjs.git",
43
+ "directory": "packages/ecosystem/packages/ssr"
44
+ },
45
+ "keywords": [
46
+ "lytjs",
47
+ "ssr",
48
+ "server-side-rendering"
49
+ ]
50
+ }