RenderService Blueprint
目的:规划下一代渲染服务以替换(或包装)现有 ArticleRender + MarkedParser 组合,降低耦合,支持插件化与增量演进。
关联文档:architecture.md, image-pipeline.md, detaildesign.md。
1. 现状问题 (Current Pain Points)
| 问题 |
说明 |
影响 |
| 逻辑集中 |
ArticleRender 同时负责读取、解析、样式拼接、延迟元素、上传协调 |
难测试 / 难替换子环节 |
| 隐式状态 |
originalMarkdown, cachedElements 内部字段耦合流程顺序 |
外部无法复用或二次解析 |
| 图片收集耦合 Marked 扩展 |
依赖前置 wikilink 转换 |
新语法添加需改内核 |
| 缺少中间 IR |
无法对 Token/AST 做多阶段转换 |
功能扩展(如统计、Lint)困难 |
| 发布耦合渲染 |
上传/发布 API 与渲染混合 |
交互模式无法独立测试 |
| 单线程串行 |
图形生成、图片上传均串行 |
性能受限 |
2. 设计目标 (Design Goals)
| 目标 |
描述 |
衡量指标 |
| 分层解耦 |
渲染、转换、资源收集、发布分离 |
新增图片语法无需改核心类 |
| 插件式中间件 |
可在 parse → transform → render 各阶段注入 |
插件注册 API 清晰 |
| 可测试 |
纯函数/无副作用阶段隔离 |
单元测试覆盖率提升 |
| IR 标准化 |
生成统一 AST / 节点类型 |
后续可序列化/缓存 |
| 并发能力 |
图形/上传并发控制 |
大图文耗时下降 |
| 可观测性 |
事件 & 钩子 |
before/after metrics 输出 |
3. 拟议分层 (Proposed Layers)
4. 关键接口 (Core Interfaces - Draft)
5. 执行模型 (Execution Model)
6. 示例阶段实现草稿
| Stage |
说明 |
是否必须 |
| loader |
读取文件与 raw |
是 |
| frontmatter |
解析 YAML -> ctx.frontmatter / ctx.meta 预填 |
是 |
| markdownImageCompat |
Markdown 图片 -> 统一节点形式 |
可选 |
| shortcodeGallery |
解析 gallery → 多个 image 节点 |
可选 |
| parser |
Marked/Remark → AST |
是 |
| imageCollect |
AST 遍历收集图片,写入 ctx.resources.images |
是 |
| coverInfer |
若无封面,从 images 按 position 选首图 |
可选 |
| renderHTML |
AST -> HTML 字符串 |
是 |
| styleInline |
合成主题/高亮,自定义 CSS 注入 |
可选 |
| finalize |
产物整理 / hash / 缓存存储 |
可选 |
7. AST 规范 (Simplified)
可基于 remark/unified 生态替换当前 marked,或构造最小抽象后桥接。
8. 事件 & Hook 设计
预定义事件:before:stageName / after:stageName / error:stageName。
9. 并发策略
- 图片上传与图形生成移出核心渲染,进入
PublisherService。
PublisherService.publish(ctx, opts):接受 RenderContext,内部:
- 对
ctx.resources.images 并发池(PromisePool)上传。
- 替换
ctx.html 中引用。
- 构建
DraftArticle / DraftImages。
10. 迁移计划 (Phased Migration)
| 阶段 |
内容 |
验证点 |
| P0 |
搭建 RenderService 空管线 + 复用旧 ArticleRender 结果 |
构建无回归 |
| P1 |
拆出 loader/frontmatter/parser/coverInfer |
旧行为对比 snapshot |
| P2 |
新 AST + imageCollect,弃用 wikilink 转换 hack |
图片计数稳定 |
| P3 |
发布逻辑重构到 PublisherService |
草稿发布一致 |
| P4 |
Hook/插件系统开放 |
外部扩展示例 |
| P5 |
并发上传 + 缓存 |
性能基线下降 |
11. 回滚策略
- 每阶段保留配置开关:
useLegacyRenderer。
- 出现渲染差异:比较 ctx.html 与 legacy.html diff 提示。
- 发布失败回退:走旧
ArticleRender.postArticle。
12. 测试策略
| 测试 |
说明 |
| Snapshot 渲染 |
同一 Markdown 输入旧 vs 新 HTML 对比 |
| AST 结构 |
断言图片/标题节点数量与顺序 |
| 封面选择 |
多组合(frontmatter + 混合图片顺序) |
| Hook 调用 |
注册 mock 钩子计次 |
| 并发上传 |
人工注入延迟 → 顺序与最终替换正确 |
13. 指标与可观测
- ctx.diagnostics 数量与类型统计。
- 阶段耗时:
performance.now() 差值注入 ctx.flags。
- 上传耗时 / 失败率。
14. 安全考量
- Stage 插件沙箱:限制访问仅上下文公开字段。
- 阶段超时(可选):超过阈值标记 warning。
- HTML 输出再次 sanitize。
15. API 草案
16. 依赖与选型比较
| 方向 |
方案 A |
方案 B |
选择建议 |
| Markdown AST |
remark/unified |
继续 marked + 自建 AST 映射 |
remark 更标准;初期可混合 |
| Hook 实现 |
事件总线 (mitt) |
简单数组回调 |
先内建数组回调,后期引入库 |
| 并发控制 |
p-limit |
自写 PromisePool |
p-limit 简洁可靠 |
17. 风险 & 缓解
| 风险 |
缓解 |
| AST 转换差异导致样式变化 |
Snapshot + 逐阶段灰度 |
| 性能倒退 |
阶段耗时基线监控;必要时跳过冗余阶段 |
| 插件滥用 Hook |
权限白名单 / 文档规范 |
| 并发上传触发限流 |
设置最大并发 + 429 重试 |
18. 成功判定 (Success Criteria)
- 同一输入 50 篇示例笔记,新旧 HTML 差异行 <= 2%(忽略动态 id)。
- 图片收集数量一致,封面判定一致率 100%。
- 20+ 图片大文档总发布耗时下降 ≥25%。
- 可插拔 demo:增加一个统计字数的 Stage 无需改核心。
19. 下一步行动 (Action Items)
- 建立
RenderService 目录与最小类骨架。
- 搬迁读取/frontmatter/封面逻辑并保留旧 API 外壳。
- 引入 AST(先轻量:仅 Image/Heading/Paragraph)。
- Snapshot 测试脚手架。
- 性能基线脚本:统计渲染 + 上传耗时。
后续若需要,我可以直接生成骨架代码与测试样例,请指示。