# Phase 5g:页面后台化(blocks 模型)与字体子集化 - 项目范围 ## 1. 问题定义 - **项目目标**:①按 docs/research/10 方案 E 把关于页改造成「块式页面构建器」(结构可增删排序)②样式即数据(theme.yaml → 构建期 CSS 变量,含对比度闸门)③首页字段细化并抽 HomePage 消 zh/en 双份 ④开源页收尾(README 缓存/回落/告警)⑤后台文档与 hint 补齐 ⑥字体子集化工具(把艺术字体单页增量从数百 KB 降到数十 KB) - **目标用户**:站长(希望整页可编辑、能上更多艺术字体)与读者(版式与可读性不退化) - **核心价值**:内容与结构的编辑权交回后台,同时守住灰阶体系/双语/SEO/构建期零运行时四条红线 ## 2. 假设与待确认 ### 2.1 已确认事实 - Sveltia 0.252 支持 list 的 types + typeKey(方案 10 §3.4 从本仓 bundle 取证),块模型可行 - 页面文案 markdown 净化(D1/D2)已在 2cab243 落地(P0 完成) - 字体实测:@fontsource CJK 切片粒度导致单页 +163KB~+8605KB;现有 6 自托管族为基线 ### 2.2 关键假设 - 块渲染器受控,破版风险低于整页 HTML 直编(方案 10 §2 对比表) - 字体子集化(pyftsubset 按页实际用字)能把艺术字体单页增量压到 ≤150KB 阈值内 ### 2.3 待确认问题 - [x] 关于页整页可编辑路线 → 用户 2026-11-02 批准方案 E(blocks + theme.yaml + 局部自由区) - [x] 字体扩充路线 → 先落 6 族,其余按子集化工具就绪后再评估(本包 T7 交付工具) ### 2.4 可选解释与取舍 - 关于页保留 intro markdown 通道作为 compat(blocks 为空时三级回落:blocks → intro → 默认文案) - 样式即数据只开放白名单旋钮(约 12 项),不开放整份 tokens.css - 图片只走 Astro image() 管线,禁止块内填外链/绝对路径(schema 层拦) ### 2.5 已证伪路径 - 整页富文本直编(C 方案):XSS 面大、无设计兜底,弃 - 新增 webfont 直接上(不子集化):单页 +535KB~+8605KB,超阈值,弃(改走 T7 工具) ## 3. 功能范围 ### 3.1 核心功能(MVP) - [ ] T1 blocks 骨架:schema(discriminatedUnion)+ page-blocks.ts + BlockRenderer + prose/tracks/divider 三块 + 后台 types 声明 - [ ] T2 块型扩充:cards/timeline/quote/figure/linklist/cta + 图标键白名单 + 图片 image() 管线 - [ ] T3 样式即数据:theme.yaml + theme.ts + BaseLayout 内联变量 + 对比度闸门脚本 - [ ] T4 首页细化与去重:抽 HomePage.astro 消 zh/en 双份 + 字段细化(projectsLimit/announcement 等) - [ ] T5 开源页收尾:README 缓存策略/超时/回落矩阵 + fallback JSON 回填 + include 未命中 WARN - [ ] T6 文档与 hint:docs/管理台.md(块编辑用法)+ 写作指南扩充 + admin 全字段中文 hint - [ ] T7 字体子集化工具:按页用字裁剪艺术字体为小切片 + build.sh 守卫挂载 + 实测对比 ### 3.2 扩展功能 - 无 ### 3.3 不在范围内 - 换 CMS、页面布局的任意拖拽网格、运行时编辑器 ## 4. 最小实现路径 - 最简单可行方案:块类型先用 3 类跑通闭环(prose/tracks/divider),再扩到 9 类;theme 只做 12 个白名单旋钮 - 暂不引入:可视化块预览、块级动画配置 - 不做的抽象:通用页面 DSL(只服务现有页面) ## 5. 技术决策 - 技术栈:Astro 7.4.4 + zod discriminatedUnion + Sveltia list/types + pyftsubset(fonttools) - 证据协议:evidence: runs - 本轮允许改动:src/content.config.ts、src/lib/{page-blocks,theme,site-content}.ts、src/components/blocks/*、src/components/pages/{AboutPage,HomePage}.astro、src/pages/{index,en/index,opensource,en/opensource}.astro、src/layouts/BaseLayout.astro、public/admin/*、content/site/*.yaml、scripts/build-perf/*、infra/deploy/build.sh、docs/*、tests/e2e.mjs - 本轮不应触碰:nginx/ESA、图库灯箱(GalleryPage/PhotoZoom)、Header/Footer 结构 - Git integration branch:`spec/2026-11-02_blog-5g-pages` ### 5.1 验证策略 - 范围级别:package - 变更对象:页面数据模型与渲染器、后台配置、样式变量生成、字体产物、文档 - 快速检查:`pnpm astro build`(node26) - 集成检查:`node tests/e2e.mjs`(37 项,本包预期新增块/主题断言)+ content-lint 0/0/0 - 全项目检查:字体体积账(三页增量)+ 视觉复核(glm-5.3-flash:max,块版式与主题变量双态);仅在构建链或 BaseLayout 结构再变更时升级范围 - 升级触发:若 theme 变量波及全局排版(字体字号全站变化)或 blocks 改动触及首页/文章页结构,升级为全站视觉复核与 E2E 全量并记录理由 ## 6. 成功标准与验证方式 - [ ] 关于页整页由 yaml blocks 驱动,增删排序生效 -> verify: task_0001 - [ ] 九类块全部可渲染且旧内容零回归(三级回落) -> verify: task_0002 - [ ] theme.yaml 改值 → 产物 CSS 变量变化,对比度闸门拦截不达标 -> verify: task_0003 - [ ] 首页 zh/en 由同一组件渲染且字段可配 -> verify: task_0004 - [ ] 开源页 README 失败矩阵与 fallback 告警可用 -> verify: task_0005 - [ ] 后台文档与 hint 完整 -> verify: task_0006 - [ ] 字体子集化工具把指定字体单页增量压到 ≤150KB -> verify: task_0007 ## 7. 风险与约束 - 灰阶体系与双语红线不变;彩色仅正文强调 - 块渲染器未知类型跳过 + WARN,绝不炸构建 - 字体子集化需保证字形覆盖(裁错字会出现豆腐块)→ 断言:子集后页面文本逐字命中 - 多车道并行:共享文件(content.config.ts/admin config/docs)按 boundary 划界,tokens/global 由 orchestrator 或指定单车道