返回文档库 页集

Yeji / Software Architecture / 2026.07

页集软件架构说明书

一份面向产品、研发、运维与内容维护者的架构基线:解释页集如何组织 HTML 文档、如何在边缘运行、 当前系统为什么保持静态优先,以及下一阶段怎样在不破坏简单性的前提下演进。

一句话架构

页集是一个由 Next.js / React 应用壳独立静态 HTML 文档TypeScript 文档索引Cloudflare Worker 边缘入口组成的只读知识书架; 搜索与筛选在浏览器完成,当前不依赖数据库和对象存储。

文档状态
初版 · 待团队确认
版本
v1.0
业务代码基线
工作区快照 2026.07.30
生成日期
2026.07.30
系统版本
0.1.0
适用范围
当前仓库与托管站点
9 文档索引条目(加入本文后)
3 独立富 HTML 长文
0 当前 D1 / R2 业务依赖
4 提交前质量门禁类别
01 / 18

文档控制与阅读约定

本文是“现状基线 + 目标建议”的组合文档。凡是尚未在代码中实现的内容都会明确标记,不能直接作为已上线能力对外承诺。

Current / 当前事实

来自代码与配置

对仓库、构建脚本、测试、运行入口与托管声明的直接归纳,可作为当前系统说明。

Target / 建议目标

可执行的演进方向

用于规划、评审和拆分任务,不代表已经承诺时间或已经具备对应服务等级。

Risk / 风险项

需要验证或治理

按影响与发生可能性排序,包含触发条件、缓解动作和建议责任角色。

项目 定义 本版内容
系统名称 页集(Yeji HTML Document Archive) 集中发布、检索与阅读 HTML 文档的响应式知识书架
主要读者 产品负责人、研发、运维、内容维护者、架构评审者 共同理解边界、依赖、风险、质量门禁与演进顺序
覆盖视图 上下文、容器、组件、运行时、数据、安全、质量、部署 接近 C4 + 运行视图 + 风险台账的组合
不覆盖 业务内容正确性、托管平台内部实现、组织预算与排期 这些内容需要由对应责任方另行确认
更新触发 新增运行时依赖、启用 D1/R2、引入登录、改变发布链路 任一条件发生时,应同步更新本文和相关 ADR
基线判断

当前系统规模小、读多写少、内容以版本库为来源,静态优先是合理选择。架构治理重点不是提前引入更多基础设施, 而是先解决内容可信、索引一致、路由唯一和发布可验证。

02 / 18

架构执行摘要

页集的设计本质是“应用负责发现,文档负责阅读,边缘负责交付”。它用较低的运行复杂度换取高可移植性和高阅读稳定性。

优势 01

静态内容是主资产

富文档以完整 HTML 文件进入 public/docs/,样式和交互可以随文档独立演进; 即使应用层功能退化,静态文件仍具备直接交付的基础。

优势 02

边缘运行且没有业务数据库

Worker 接住应用请求与图片优化,文档索引在构建时进入应用。没有网络数据库查询, 因而读路径短、部署面小、日常运维成本低。

关键权衡

两条阅读路径并存

高价值长文走 /docs/*.html 独立页面;普通索引条目走 /docs/[slug] 通用模板。灵活性更高,但会带来路由、导航和样式一致性的治理成本。

首要治理点

把手工约定变成机器校验

文档文件、索引记录和页面链接目前依赖人工同步。下一阶段最有价值的改进是唯一清单、 路由一致性测试、内容安全检查和最小可观测性。

架构适配度(定性评估)

维度 当前适配度 判断依据 主要缺口
阅读与分发 静态文档、响应式布局、目录、打印、阅读进度 独立文档之间的设计语言尚未完全统一
运行成本 无业务数据库、边缘交付、依赖少 仍需建立资源量与流量基线
可维护性 类型、Lint、测试和 CI 已存在 手工索引、正则导入脚本、双路由重复
安全治理 只读、无持久化输入、密钥不入库 同源 HTML 脚本信任、CSP 与依赖扫描未形成门禁
可观测性 开发日志路径已配置 没有应用级错误率、性能、文档 404 与发布健康指标
建议目标 先治理一致性,再扩展平台能力

在没有多人在线编辑、权限化管理、业务分析或大媒体资产需求之前,不建议仅为“架构完整”而启用 D1、R2 或后台管理系统。

03 / 18

系统范围与上下文

页集位于内容作者与读者之间:作者通过版本库交付内容,读者通过浏览器访问,CI 和托管平台构成发布控制面。

参与者与责任

参与者 / 系统 核心目标 与页集的交互 信任级别
读者 快速找到并稳定阅读内容 发送匿名 GET 请求;在浏览器内搜索、筛选、打印 不可信输入边界
内容作者 发布完整、可维护的长文 提交 HTML 和资源;补齐元数据 受控贡献者
研发 / 维护者 保持系统可构建、可发布、可回滚 变更应用代码、脚本、配置和质量门禁 高信任角色
GitHub Actions 阻断不合格变更 执行安装、Lint、类型检查、构建与页面测试 自动化控制面
OpenAI Sites / Cloudflare 托管与边缘执行 提供 Worker、ASSETS、IMAGES 及可选资源绑定 平台依赖
系统内
  • 首页、文档索引和浏览器交互
  • 通用阅读器与独立 HTML 长文
  • Worker 请求入口和图片优化路由
  • 内容导入脚本、测试与 CI 配置
  • 可选的 D1 / R2 接入骨架
系统外
  • 原始研究资料与内容事实核验
  • GitHub、Sites、Cloudflare 的平台内部实现
  • 域名、访问策略和组织身份的管理后台
  • 终端浏览器、打印机与 PDF 阅读软件
  • 未来可能接入的分析、搜索或内容管理服务
04 / 18

架构目标与质量属性

架构优先级从“内容可达、可读”开始,再到可维护、安全与扩展。所有目标都需要可验证的场景,而不仅是原则性表述。

质量属性 优先级 当前机制 验证场景
可发现性 P0 标题、主题、摘要检索;分类筛选;更新时间与标题排序 读者在一个入口内定位已知或模糊目标文档
可读性与无障碍 P0 语义化结构、跳转链接、原生控件、响应式、打印、减弱动态效果 键盘、窄屏、打印和辅助技术用户可完成核心任务
可用性 P0 静态资产 + 边缘交付,无业务数据库依赖 单篇文档访问不被数据服务故障阻断
性能 P1 边缘 Worker、静态文件、图片优化、客户端内存搜索 首页和长文在常见网络与移动设备上快速可用
可维护性 P1 TypeScript、ESLint、测试、CI、文档导入脚本 新增文档后能自动发现文件、索引、链接和结构错误
安全与隐私 P1 只读产品、无业务输入持久化、密钥不入库、安全回跳校验 恶意请求、恶意 HTML 或错误身份回跳不能扩大权限
可观测性 P2 开发工具日志路径 发布后能在分钟级发现错误率、404 或性能退化

建议的服务目标

建议目标 以下为下一阶段可采用的度量基线,当前仓库没有证据表明这些目标已被持续测量。

≥ 99.9% 月度公开阅读路径可用性
≤ 2.5s 移动端 p75 LCP 目标
≤ 0.1 页面 p75 CLS 目标
100% 已索引直达文档通过结构与链接检查
0 发布时严重无障碍与高危安全问题
≤ 10 min 故障版本识别到完成回滚
质量属性之间的主要张力

独立 HTML 允许每篇长文获得最佳表达,但会削弱全站一致性和集中治理;统一模板更容易维护, 却限制复杂图表与专属交互。当前“双路径”是有意识的折中,前提是建立明确的选路标准。

05 / 18

技术栈与关键约束

应用采用 Next.js 编程模型,但生产运行形态是由 vinext 与 Vite 构建的 Cloudflare Worker,而不是传统常驻 Node.js 服务器。

层级 技术 / 版本 职责 架构约束
UI / 应用 Next.js 16.2.12、React 19.2.6 App Router、Server / Client Component、元数据、状态页 路由和组件需兼容 vinext 支持面
构建 vinext 0.0.50、Vite 8.0.13 把 Next.js 应用构建为边缘可运行产物 输出应为 Worker 兼容 ESM,不能依赖常驻 Node 进程
边缘运行 Cloudflare Vite Plugin 1.37.1、Wrangler 4.92.0 本地模拟、绑定注入、Worker 运行和静态资源 使用 nodejs_compat,平台绑定由环境提供
语言 TypeScript 5.9.3、Node ≥ 22.13.0 应用、Worker、数据库适配与构建配置 strict 开启;模块解析为 bundler
数据预留 Drizzle ORM 0.45.2、Drizzle Kit 0.31.10 未来 D1 表结构和类型化访问 当前 schema 为空,D1 绑定未启用
样式 全局 CSS + 文档内联 CSS;Tailwind 构建依赖已存在 应用壳统一样式和独立长文专属样式 当前页面主要使用手写 CSS,不应假设已有组件库
约束 01

边缘兼容

运行时代码应使用 Web API 或经验证的兼容接口;避免文件系统、长连接进程与本地磁盘假设。

约束 02

内容可移植

直达 HTML 使用站内相对路径,不依赖作者机器绝对路径;理想情况下无外部运行依赖。

约束 03

配置与密钥分离

.openai/hosting.json 只声明项目和逻辑资源;运行时密钥应由托管环境注入。

当前事实 依赖版本为精确版本

package.jsonpackage-lock.json 固定了当前依赖组合,有利于可重复构建; 但 vinext 和平台插件仍处于快速演进区,应通过升级分支和完整检查验证兼容性。

06 / 18

逻辑分层架构

系统可以划分为体验、内容领域、应用运行、边缘适配和平台资源五层。业务依赖从上向下,内容模型不应反向依赖具体托管实现。

分层规则

  • 文档元数据属于内容领域,不应散落在 UI 组件中。
  • 首页交互只消费 DocumentItem[],不直接读取文件系统。
  • 平台绑定通过 Worker / 数据适配层进入,不应出现在展示组件中。
  • 独立 HTML 可以拥有专属表现,但必须遵循安全、链接和无障碍底线。
  • 数据库和对象存储是需求触发的可选能力,不是默认依赖。
  • 构建与测试对内容文件同样负责,不能只验证 React 应用。
  • 通用阅读器与独立长文共享导航语义,而非强制共享全部 CSS。
  • 任何跨层捷径都应通过 ADR 记录原因、期限和退出条件。
07 / 18

容器与组件设计

这里的“容器”指可独立理解的运行或交付单元,不等同于 Docker 容器。当前主要由应用壳、静态文档集与边缘入口组成。

容器 / 组件 位置 运行位置 责任 状态
根布局与元数据 app/layout.tsx 边缘服务端 语言、动态 metadataBase、图标、Open Graph、Twitter 元数据 在用
首页服务端入口 app/page.tsx 边缘服务端 把静态文档索引传给客户端组件 在用
首页交互 app/components/HomeClient.tsx 浏览器 搜索、筛选、排序、移动菜单和发布说明对话框 在用
文档目录 app/lib/documents.ts 构建期 / 服务端 / 客户端数据 定义 DocumentItem 与当前全部文档元数据 唯一手工索引
通用阅读器 app/docs/[slug]/page.tsx 边缘服务端 + 浏览器 静态参数、页面元数据、通用正文模板、下一篇导航 在用
阅读器交互 ReaderActions.tsx 浏览器 滚动进度、复制链接、打印与提示 在用
独立 HTML 文档 public/docs/*.html 浏览器 / 静态资产 完整长文、专属 CSS、目录与页面内交互 3 篇
Worker 入口 worker/index.ts Cloudflare Worker 图片优化分流,其余请求交给 vinext App Router handler 在用
身份辅助 app/chatgpt-auth.ts 边缘服务端 读取身份头、要求登录、安全构造登录/登出回跳地址 当前路由未调用
D1 数据适配 db/index.tsdb/schema.ts 边缘服务端 可选 Drizzle D1 连接;无绑定时显式报错 未启用

源代码组件树

app/
├─ layout.tsx                 # 站点元数据与根布局
├─ page.tsx                   # 首页服务端入口
├─ components/
│  └─ HomeClient.tsx         # 搜索、筛选、排序与首页交互
├─ docs/[slug]/
│  ├─ page.tsx               # 通用阅读器
│  └─ ReaderActions.tsx      # 进度、复制、打印
├─ lib/documents.ts          # 文档索引与 DocumentItem
├─ loading.tsx               # 路由加载态
├─ error.tsx                 # 可恢复错误态
├─ not-found.tsx             # 404
└─ chatgpt-auth.ts           # 可选身份能力

public/docs/                 # 独立富 HTML 文档
worker/index.ts              # Worker fetch 入口
db/                          # 可选 D1 适配(当前空 schema)
scripts/                     # 文档导入 / 转换
tests/                       # 构建产物与文档结构测试
风险项 “存在代码”不等于“能力已启用”

身份和数据库辅助代码属于预留骨架;当前页面没有调用 requireChatGPTUser()getDb(), 托管声明中的 D1 / R2 也均为 null。产品说明不得把它们表述为现有功能。

08 / 18

关键请求与数据流

不同 URL 进入不同的交付路径。理解这些路径,是定位 404、样式不一致、图片失败和导航错误的基础。

A. 首页发现流程

B. 独立富文档流程

C. 通用阅读器流程

D. 图片优化流程

路由责任矩阵

URL 类型
内容来源
交互实现
主要责任方
/
documents.ts + React
HomeClient
应用维护者
/docs/name.html
public/docs/*.html
文档内联脚本
内容作者 + 维护者
/docs/:slug
DocumentItem + 通用模板
ReaderActions
应用维护者
/_vinext/image
ASSETS + IMAGES
Worker
平台 / 运行时维护者
风险项 同一 slug 存在两种 URL 语义

对带 href 的富文档,首页访问 /docs/slug.html,但 generateStaticParams() 仍为 /docs/slug 生成通用页面;下一篇导航也固定使用无后缀路由。 这可能造成内容重复、分享链接不一致和读者跳转到示例模板。

09 / 18

内容模型与发布流程

页集目前采用“文件即内容、TypeScript 数组即目录”的模型。它简单、透明、适合版本控制,但依赖强约定和发布前检查。

DocumentItem 领域模型

字段 必填 用途 约束 / 注意事项
slug 稳定标识与通用路由参数 应唯一、URL 安全;当前没有自动唯一性校验
href 覆盖默认动态路由,直达独立 HTML 文件必须真实存在;建议只允许站内绝对路径
title 卡片、元数据和搜索 应与文档 h1 / title 保持一致
category 分类筛选与主题展示 当前是自由文本,易产生同义分类
description 卡片摘要、页面描述与搜索 应简明且不包含不受信任 HTML
updated 机器排序 使用 ISO YYYY-MM-DD
updatedLabel 面向读者显示 与 updated 重复,存在漂移风险
readingTime 阅读预期 当前为展示字符串,未自动计算
version 内容版本 当前无版本比较或历史归档机制

当前发布流水线

内容入口策略

选择独立 HTML
  • 长篇研究、架构或工程治理文档
  • 需要复杂表格、专属图示、主题或页面内搜索
  • 希望脱离应用仍可单文件阅读和打印
  • 愿意承担独立样式与脚本的维护成本
选择通用阅读器
  • 结构固定、内容较短、无需专属交互
  • 优先追求全站一致和低维护成本
  • 希望统一继承应用元数据、导航和错误状态
  • 正文未来可由结构化来源生成
建议目标 建立单一可验证的内容清单

可将 DocumentItem 迁移为 JSON / TypeScript 清单并增加 schema 校验,构建时验证 slug 唯一、 href 文件存在、title 一致、日期合法、站内链接有效;不必立即引入 CMS。

10 / 18

运行时与部署拓扑

本地和生产使用同一套 vinext / Vite 构建链。生产入口是 Worker,静态文档与应用产物一起被托管版本交付。

构建配置事实

配置点 当前值 / 行为 意义
应用插件 vinext() + sites() + cloudflare() 同时提供 Next 编程模型、Sites 产物约定和边缘环境
Worker main ./worker/index.ts 显式接管 fetch 与图片优化
兼容标志 nodejs_compat 允许使用平台提供的 Node 兼容能力
Vite 环境 rsc,子环境 ssr 支持 React Server Components 和服务端渲染
开发状态 Wrangler / Miniflare 状态写入项目内 .wrangler 避免污染用户全局目录,便于隔离与清理
托管资源 project_id 已配置;d1: nullr2: null 当前部署不要求数据库或对象存储
测试产物 dist/server/index.js 测试直接导入构建后的 Worker 并发起 Request
生成配置 Worker ES module;兼容日期 2026-05-15;observability 开启 值来自当前构建产物,仓库没有独立的 wrangler.toml / json 源配置
Sites 版本材料 构建插件把 hosting 声明与 drizzle/ 复制到 dist/.openai 托管版本可同时携带逻辑资源声明与迁移元数据

环境与绑定

绑定 / 环境 本地 生产 失败影响
ASSETS Cloudflare 本地环境提供 托管平台注入 静态文档和源图片无法读取
IMAGES 平台模拟 / 注入 需由 Sites / 平台注入;当前生成 Wrangler 配置未显式列出 /_vinext/image 路径失败;普通 HTML 仍可能可读
DB 未声明 未声明 当前无影响;调用 getDb 时会显式报错
R2 未声明 未声明 当前无影响
身份请求头 通常不存在 由访问控制层决定 当前页面未要求身份,不影响公开阅读路径
回滚模型

内容与应用同版本交付,最安全的回滚是重新部署上一个已验证版本,而不是在线修改生产文件。 发布记录应保留版本、提交、验证结果和回滚理由。

建议目标 把生成部署配置当作可审查契约

依赖升级可能改变兼容日期、绑定或资产行为。CI 应保存或比对关键生成配置,并在真实托管环境冒烟验证 ASSETS、IMAGES 和主要路由,而不是只依赖本地构建成功。

11 / 18

数据、状态与存储策略

当前系统没有业务数据库。持久事实来自 Git 版本库中的索引和 HTML,运行时状态主要存在于单次浏览器会话。

持久内容

版本库

  • DocumentItem 元数据
  • 独立 HTML 与站内资源
  • 应用代码、脚本、测试与配置
会话状态

浏览器内存

  • 搜索词、分类、排序方式
  • 移动菜单和对话框状态
  • 阅读进度与提示消息
预留能力

D1 / R2

  • D1:结构化记录与关系查询
  • R2:大文件与媒体对象
  • 当前均未绑定、未承载业务数据

状态分类与生命周期

数据 来源 生命周期 敏感性 恢复方式
文档正文 版本库文件 随版本长期保存 取决于内容;默认应视为可发布资料 Git 历史 / 上一部署版本
文档元数据 documents.ts 随版本长期保存 Git 历史
搜索与筛选 浏览器操作 页面会话 低;不上传 无需恢复
主题偏好 独立文档浏览器设置 可选 localStorage 用户重置
托管配置 .openai/hosting.json 项目生命周期 项目标识,不应包含密钥 版本库 + 平台控制面
启用前必须修正 D1 绑定契约与迁移链尚未闭合

当前 db/schema.ts 为空、迁移 journal 没有条目,脚本只提供 generate 而没有 migrate / rollback / backup。更重要的是,hosting 声明可填任意 D1 绑定名,而 getDb() 固定读取 env.DB;Worker 的手写 Env 又把 DB 声明为必填。启用前应统一绑定名、生成类型并补齐环境化迁移流程。

何时引入持久化

启用 D1 的触发条件
  • 需要在线编辑、审批、收藏、评论或权限记录
  • 文档元数据无法继续在构建期维护
  • 需要服务端复杂筛选、审计与事务一致性
  • 可以承担 schema 迁移、备份和数据访问治理
启用 R2 的触发条件
  • 大型图片、附件或视频不适合进入 Git
  • 需要独立生命周期、版本或访问控制
  • 静态资源总量和构建时间成为明确瓶颈
  • 已定义对象命名、清理、备份和引用完整性策略
建议目标 引入存储前先写数据 ADR

ADR 至少回答数据所有者、分类、保留期、迁移、备份、恢复、删除、访问审计和故障降级; 若这些问题没有答案,新增绑定只会扩大运维面。

12 / 18

安全与隐私架构

当前攻击面小,但“可执行的独立 HTML 与主站同源”是最重要的信任边界。只读并不等于没有脚本、供应链或内容泄露风险。

主要信任边界

边界 进入的数据 当前控制 剩余风险
互联网 → Worker URL、查询参数、请求头 平台隔离、路由分发、图片宽度白名单 缺少应用级速率、异常与安全头证据;元数据生成依赖转发 Host
内容贡献 → 版本库 HTML、CSS、JavaScript、图片、链接 代码评审、CI 结构测试、禁止当前文档远程图片 同源脚本可访问站点能力;无统一内容安全扫描
构建依赖 → 产物 npm 包、Actions、插件 锁文件、固定版本、CI 只读 contents 权限 没有依赖漏洞 / 许可证 / SBOM 门禁
托管平台 → 应用 ASSETS、IMAGES、身份头、未来 DB/R2 逻辑资源声明与运行密钥分离 绑定契约、身份头来源和失败策略需持续验证

已有控制

  • 核心产品为只读浏览,没有表单数据持久化。
  • .env、令牌和 IDE 本地配置被明确排除在版本控制之外。
  • 身份回跳只接受同源相对路径,并排除登录、登出和回调保留路径。
  • 全名头只在声明 percent-encoded UTF-8 时解码,异常解码安全返回 null。
  • 现有文档测试禁止通过 HTTP(S) 加载外部图片。
  • 未见应用代码显式配置 CSP、Permissions-Policy 等响应头。
  • 独立文档允许内联脚本,必须假设内容作者具有同源代码执行能力。
  • PowerShell 导入依赖正则替换,可能把未预期标记带入最终文档。
  • 身份辅助尚未接入页面,不能视作路由保护。
  • CI 未包含依赖审计、秘密扫描或静态安全分析。

威胁与缓解

威胁 可能路径 影响 建议缓解
恶意文档脚本 将未审查 HTML 放入 public/docs 同源脚本执行、钓鱼、未来身份信息滥用 仅接收可信内容;脚本白名单 / 静态扫描;不可信内容隔离到无凭证独立域
XSS / 标记注入 未来从外部系统读取标题或正文并使用 HTML 注入 会话与内容完整性受损 继续使用 React 文本转义;外部 HTML 必须清洗;禁止危险 innerHTML
开放重定向 伪造登录 return_to 用户被引导到钓鱼站点 保留现有 safeRelativeReturnPath 测试,并覆盖编码与协议边界
供应链污染 依赖、Action 或构建插件被替换 构建产物被植入代码 依赖审计、更新策略、最小 CI 权限、来源固定与产物复核
Host / 元数据污染 不可信代理头进入 metadataBase 分享 URL 错误、缓存或 SEO 污染 仅信任受控代理覆写的头;对协议和主机做允许列表或使用固定站点基址
敏感内容误发布 把内部资料作为静态文档提交 不可逆的信息暴露与缓存扩散 内容分级、发布审批、敏感词 / 秘密扫描、明确站点访问策略
P0 治理原则 不可信 HTML 不得与身份化主站同源

如果未来允许用户上传或在线生成 HTML,应采用严格清洗、沙箱 iframe 或独立无凭证域名; 不能沿用当前“将文件直接放入 public/docs”的可信作者模型。

13 / 18

性能、可靠性与可观测性

静态优先天然降低了故障面,但当前缺少运行数据闭环。优化应先测量,再针对真实瓶颈,而不是先增加缓存或搜索基础设施。

当前优势

短读路径

直达文档无需数据库或外部 API;首页元数据随应用输出;边缘执行减少源站往返。

当前成本

全量元数据水合

首页把全部 DocumentItem 传给客户端并做 O(n) 检索;小规模合适,大规模需重新评估。

当前缺口

平台开关不等于运行闭环

生成配置已开启 observability,但仓库未定义采样、结构化日志、Web Vitals、404、告警与版本关联策略。

容量演进触发点

建议阈值 以下不是平台上限,而是用于触发重新测量和设计评审的经验门槛。

信号 继续当前方案 触发评审 可能演进
文档条目数 < 500 接近 500 或首页载荷明显增长 生成轻量搜索索引、分区加载或服务端查询
静态媒体 可接受的 Git / 构建体积 克隆、构建或部署时间明显恶化 R2 + 资源清单 + 生命周期策略
更新频率 随代码版本发布 内容团队需要独立高频发布 内容清单自动生成或受控 CMS 流程
个性化需求 匿名统一内容 收藏、权限、审批或审计成为刚需 身份边界 + D1 + 权限模型

已知性能细节

  • HomeClient 的同步文档列表随服务端 HTML 输出,浏览器水合只负责交互增强;路由级 loading.tsx 负责真实等待状态。
  • 客户端搜索把标题、摘要与分类拼接后做小写包含匹配,结果即时但不支持分词、拼音、权重与高亮。
  • Worker 图片优化限制宽度集合,避免任意尺寸放大处理面;SVG 默认绕过优化端点。
  • 独立文档将 CSS / JS 内联,减少请求数并增强可移植性,但会增加单个 HTML 体积并降低跨文档缓存复用。
  • 全局样式提供响应式、打印与 reduced-motion;发布前仍应以真实内容检查超宽表格和长代码。

失败模式与降级

失败模式 当前表现 影响范围 建议检测 / 处置
未知路由 展示中文 404 页面 单个请求 监控 404 比例;校验内部链接
应用渲染异常 展示可重试错误页 受影响路由 记录异常指纹、发布版本和请求路径
HTML 文件缺失 静态 404;首页仍可能展示卡片 单篇富文档 CI 校验 href 文件存在
IMAGES 不可用 优化端点失败 经优化图片 告警绑定错误;关键图可提供原图回退
客户端 JavaScript 禁用 首页初始内容可见,但筛选和工具不可用 交互增强 保持 SSR 内容与原生链接;避免核心正文依赖 JS

最小可观测性方案

发布信号
  • 构建成功率与耗时
  • 部署版本、提交和发布时间
  • 首页、三篇富文档的合成探测
  • 回滚次数与原因
运行信号
  • Worker 5xx、静态 404、图片优化失败率
  • 首页与文档的 LCP / CLS / INP
  • 热门文档与无结果搜索(需隐私审查)
  • 错误版本关联与告警降噪
14 / 18

测试、CI 与质量门禁

当前测试重心是“构建产物能否服务首页”和“富文档结构是否完整”。它覆盖了关键冒烟路径,但尚未形成完整的行为、可访问性与安全回归网。

当前质量链

验证层 当前覆盖 证据 主要缺口
静态规范 ESLint、TypeScript strict npm run lintnpm run typecheck 独立 HTML 内联脚本不在 TypeScript / ESLint 覆盖内
构建冒烟 导入 dist/server/index.js,请求首页并断言 200 / HTML tests/rendered-html.test.mjs 没有真实平台绑定与生产 URL 探测
首页契约 语言、标题、主要文案、文档链接、跳转链接、无预览残留 正则断言服务端 HTML 搜索、筛选、排序、对话框和移动菜单行为未测试
富文档结构 章节数量、锚点、进度、复制、响应式、表格、远程图片 读取 HTML 并做结构正则 链接有效性、标题一致、重复 ID、脚本运行与视觉回归
导入器契约 转换脚本与已发布布局关键规则一致 脚本文本断言 没有以样例输入执行端到端转换并比较语义输出
CI main 的 push / pull_request,Ubuntu,Node 22.13.0,15 分钟上限 .github/workflows/ci.yml 无依赖安全、可访问性、断链与部署后检查

建议的增量测试金字塔

L1 / 快速

纯逻辑单测

搜索、排序、slug / href 解析、安全回跳、日期与分类规范化。

L2 / 契约

内容清单检查

唯一 slug、文件存在、内部链接、重复 ID、title / h1 / 索引一致。

L3 / 集成

Worker 路由

首页、通用文档、静态 HTML、404、图片优化和绑定缺失行为。

L4 / 发布

浏览器与探测

键盘、窄屏、打印、Web Vitals、生产链接和部署后冒烟。

推荐发布门禁顺序

先运行毫秒级逻辑与清单校验,再进行类型和构建,最后执行浏览器 / 部署探测。 失败信息应直接指向文档 slug、文件、锚点或路由,降低内容维护者的排查成本。

15 / 18

架构决策记录摘要

下表把代码中已经形成的关键选择显式化。后续如推翻任一选择,应新建 ADR,而不是静默改变隐含前提。

ID 决策 状态 理由 代价 / 退出条件
ADR-001 静态内容优先 Accepted 读多写少、内容可版本化、运行依赖少 在线协作与个性化成为核心需求时重审
ADR-002 富文档与通用阅读器双路径 Accepted with debt 在表达自由度与一致维护之间折中 必须建立唯一 URL、导航和准入标准
ADR-003 浏览器端搜索与筛选 Accepted 数据量小、零网络请求、交互即时 载荷或搜索质量不满足目标时重审
ADR-004 vinext / Vite 构建到 Cloudflare Worker Accepted 保留 Next 编程模型并获得边缘交付 升级需验证兼容面与产物契约
ADR-005 TypeScript 数组作为文档清单 Temporary 实现最简单、类型明确、当前规模可控 手工漂移增多时迁移到可生成、可校验清单
ADR-006 D1 / R2 默认关闭 Deferred 当前没有持久化业务需求 触发条件见数据与存储章节
ADR-007 独立文档尽量无外部依赖 Accepted 可移植、可离线阅读、避免第三方失效 以 HTML 体积和跨页复用为代价
ADR-008 身份能力按需接入 Deferred 当前核心阅读路径不需要应用内身份 出现私有分区或用户数据时先完成权限模型

ADR 模板

# ADR-XXX:决策标题

- 状态:Proposed / Accepted / Superseded / Rejected
- 日期、责任人、关联需求
- 上下文:什么变化迫使我们决策?
- 决策:选择什么?明确不选择什么?
- 备选:至少一个可行替代方案
- 后果:收益、成本、风险与迁移影响
- 验证:怎样证明决策有效?
- 退出条件:何时必须重新评审?
- 迁移与回滚:失败时如何安全退出?
16 / 18

风险台账与技术债

风险按“影响 × 发生可能性 × 可检测性”综合排序。优先级用于安排治理顺序,不代表每项都需要立即重构。

ID 风险 影响 可能性 优先级 建议动作 责任角色
R-01 不可信独立 HTML 在主站同源执行脚本 P0 限定可信作者;内容脚本检查;未来上传隔离域 / sandbox 安全 + 内容平台
R-02 /docs/slug/docs/slug.html 内容和导航不一致 P1 定义 canonical URL;所有导航统一使用 resolveDocumentHref 应用维护者
R-03 HTML 文件与手工索引漂移 P1 schema + 文件存在 + slug 唯一 + title 一致性测试 内容平台
R-04 仓库未显式配置统一安全响应头 P1 核对托管默认值;设计兼容内联文档的 CSP 迁移方案 运行时 + 安全
R-05 测试以正则结构断言为主,真实交互和无障碍回归不足 P1 增加逻辑单测、DOM 契约、键盘与窄屏冒烟 质量负责人
R-06 缺少应用级可观测性,发布后退化发现慢 P1 建立合成探测、错误率、404、Web Vitals 和版本关联 运行时维护者
R-07 正则式导入脚本对源 HTML 结构敏感 P2 固定样例输入;执行端到端转换;逐步采用 DOM 解析 内容工具维护者
R-08 数据库、身份和示例代码增加认知噪声 P2 明确标注可选;不使用则移动到示例或删除死代码 架构维护者
R-09 updated 与 updatedLabel 双字段可能不一致 P2 仅保存 ISO 日期,显示层统一格式化 内容平台
R-10 根元数据直接使用转发协议与 Host 构造站点基址 低至中 P2 确认可信代理覆盖;增加协议 / 主机允许列表或固定生产基址 运行时 + 安全
R-11 D1 配置可使用任意绑定名,但数据适配固定读取 env.DB 高(启用后) P1 启用前统一绑定契约、生成 Env 类型,并增加真实 D1 集成测试 数据 + 运行时
R-12 图片优化依赖 IMAGES,但生成 Wrangler 配置未显式列出绑定 P1 确认 Sites 注入契约;部署后冒烟;缺失时提供结构化错误或原图降级 运行时 + 平台
R-13 生产 Wrangler 配置完全由构建生成,升级可能静默改变运行契约 P2 在 CI 快照和比对关键配置、兼容日期、资产目录与可观测性开关 运行时维护者

推荐处理顺序

  1. 先守边界:明确独立 HTML 的可信作者模型与未来不可信内容隔离方案。
  2. 再消除歧义:统一文档 URL 解析、下一篇导航和 canonical 元数据。
  3. 把约定自动化:用清单 schema 和文件 / 链接检查阻断索引漂移。
  4. 补发布闭环:增加最小合成探测、错误指标和部署版本关联。
  5. 最后降维护成本:重构导入器、删除死骨架、统一重复元数据。
17 / 18

演进路线图

路线遵循“治理先于扩容、证据先于基础设施”。每一阶段都应能独立交付价值,也能在需求没有增长时安全停留。

0—30 天 / 基线治理

让现状可靠

  • 统一 resolveDocumentHref 与下一篇导航
  • 确定富文档 canonical URL
  • 增加 slug、href、title、内部链接检查
  • 保持同步列表服务端直出,避免重新引入假加载
  • 核对并记录生产安全响应头
  • 确认 ASSETS / IMAGES 的真实托管绑定契约
  • 建立首页和关键文档合成探测
31—90 天 / 工程化

把约定变成平台

  • 结构化内容清单与 schema 校验
  • 从清单生成首页索引与静态参数
  • 导入器端到端样例测试
  • 键盘、窄屏、断链与可访问性门禁
  • 发布版本、错误率、404 和 Web Vitals 看板
  • 在 CI 比对生成的 Worker / Wrangler 关键配置
  • 依赖审计和敏感内容扫描
90 天以后 / 按需扩展

只为真实需求增加状态

  • 文档量增长后生成轻量全文索引
  • 大型媒体增长后引入 R2
  • 收藏、审批或在线编辑出现后引入 D1
  • 启用 D1 前统一绑定名、类型、迁移与备份流程
  • 私有分区出现后接入身份与授权
  • 不可信内容使用隔离域或沙箱
  • 形成正式 ADR 库与季度架构复盘

目标架构原则

原则 01

一个内容事实源

文件、元数据、路由和导航由同一清单派生,杜绝多处手工重复。

原则 02

一条 canonical 路径

每篇内容只有一个分享、索引和 SEO 主 URL;兼容入口只做明确重定向。

原则 03

可信内容与不可信内容隔离

作者信任模型进入架构,不把可执行 HTML 当作普通数据文件处理。

原则 04

静态是默认,状态是例外

只有明确业务场景和运维责任时才引入数据库、对象存储或身份化路径。

原则 05

发布即验证

构建、内容契约、安全、可访问性和部署探测共同定义“可以发布”。

原则 06

指标驱动扩展

以真实文档量、体积、性能和协作需求触发架构升级,而非预设复杂度。

路线图的停止规则

如果当前静态方案持续满足质量目标,可以停留在任一阶段。架构成熟度不由服务数量衡量, 而由边界是否清楚、失败是否可见、变更是否可验证来衡量。

18 / 18

运维手册、责任边界与附录

本节把架构落到日常动作:如何验证、如何发布、出现问题先查哪里,以及哪些文件是各类能力的事实来源。

常用操作

场景 操作 通过标准
首次安装 npm ci 依赖严格按锁文件安装,无未解释的版本改写
本地开发 npm run dev 首页、通用路由和独立 HTML 可访问
完整检查 npm run check Lint、类型、构建与页面测试全部通过
单独构建 npm run build 生成 Worker 兼容生产产物,无关键警告
新增文档 放入 public/docs,更新索引和测试 首页可发现、链接可达、移动端 / 打印可读
回滚 选择上一个已验证站点版本重新部署 关键 URL 探测恢复,错误率回落,并记录原因

故障排查速查

首页正常,但某篇独立 HTML 返回 404
  1. 核对 documents.ts 的 href 与 public/docs 文件名,包括大小写和后缀。
  2. 确认文件被纳入构建 / 部署版本,而不是只存在于本地。
  3. 检查是否把无后缀通用路由当作富文档 canonical URL。
  4. 修复后运行完整检查并重新部署,不要在线补文件。
首页出现文档,但点击后进入示例模板
  1. 确认该条目是否需要 href: "/docs/name.html"
  2. 检查导航是否硬编码为 /docs/${slug}
  3. 统一通过文档 URL 解析函数生成首页和“下一篇”链接。
图片优化失败,但原始文档文本仍可访问
  1. 确认请求是否进入 /_vinext/image
  2. 检查 ASSETS 能否找到原图以及 IMAGES 绑定是否存在。
  3. 确认宽度属于默认设备尺寸或图片尺寸白名单。
  4. 关键内容应提供原图或文本替代,不让优化服务成为正文单点。
构建通过,但发布页面内容不符合预期
  1. 核对部署版本对应的提交和构建产物。
  2. 检查独立 HTML 是否由导入脚本重新生成后未提交。
  3. 确认缓存和 canonical URL,没有访问到另一条阅读路径。
  4. 若无法快速定位,回滚到上一个已验证版本后再离线分析。

发布完成定义

内容
  • 标题、摘要、分类、版本与更新时间准确
  • 正文来源和引用已由内容责任人确认
  • 内部链接、锚点、图片和表格可用
  • 不存在敏感信息或未经授权资料
工程
  • 唯一 URL 与首页、下一篇导航一致
  • 键盘、窄屏、打印和减弱动态效果可用
  • 完整检查通过并记录构建证据
  • 部署后关键 URL 探测成功,回滚版本可用

责任分工

事项 主责 协作 最终确认
内容事实与授权 内容作者 / 业务负责人 编辑、法务或安全 内容所有者
索引、路由与阅读体验 前端 / 应用维护者 内容维护者、设计 产品负责人
Worker、绑定与部署 运行时维护者 平台、安全 技术负责人
质量门禁与发布证据 变更作者 质量负责人、评审者 合并审批者
架构决策与风险台账 架构维护者 产品、研发、运维、安全 技术负责人

关键文件地图

问题 首先查看 其次查看
首页有哪些文档? app/lib/documents.ts app/components/HomeClient.tsx
文档 URL 为什么这样生成? documents.ts 的 href / slug app/docs/[slug]/page.tsx
请求如何进入边缘应用? worker/index.ts vite.config.ts
当前是否使用数据库或对象存储? .openai/hosting.json db/index.tsdb/schema.ts
发布前检查什么? package.json scripts tests/rendered-html.test.mjs、CI workflow
富文档如何生成? scripts/import-*.ps1 public/docs/*.html
品牌与页面语言是什么? brand-spec.md app/globals.css

术语表

ASSETS

Worker 环境中的静态资源读取绑定。

IMAGES

平台图像变换能力,用于缩放、格式与质量输出。

D1

Cloudflare 边缘 SQLite 数据库;当前未启用。

R2

对象存储;适合大媒体与附件,当前未启用。

RSC

React Server Components,在服务端生成组件结果。

Canonical URL

一份内容被搜索、分享与引用时采用的唯一主地址。

架构文档维护规则

每次启用新绑定、改变 canonical 路由、引入身份化页面、修改内容信任模型或替换构建运行时, 都应更新对应章节、风险台账和 ADR;至少每季度复核一次“当前事实”标签。