尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

FluentRead 架构深度解析:WXT + Vue 3 的模块边界、依赖方向与可验证迁移

发布时间:2026/9/28 21:25:39

资讯中心
01
ARTICLE

FluentRead 架构深度解析:WXT + Vue 3 的模块边界、依赖方向与可验证迁移

FluentRead 架构深度解析:WXT + Vue 3 的模块边界、依赖方向与可验证迁移
前端AI 应用本地部署【免费下载链接】FluentReadAn open-source browser extension for bilingual translation. 一款开源的浏览器双语翻译插件。项目地址https://gitcode.com/gh_mirrors/fl/FluentRead点击查看免费下载本文以仓库 docs/architecture.md 为骨架结合src/、entrypoints/、tests/architecture/与wxt.config.ts等源码佐证完整梳理 FluentRead 的架构目标、目录契约、依赖硬规则、翻译链路、插件生命周期与测试门禁。读完本文你将掌握这套浏览器双语翻译插件如何用编译期静态注册 运行时生命周期替代 IoC 容器如何在 MV2/MV3、Chrome/Firefox、扩展与 userscript 多出口之间保持单一实现以及如何通过 fitness tests 让架构边界可编译、可测试、可回归。技术栈与架构基调FluentRead 是一个开源的浏览器双语翻译插件扩展名FluentRead-流畅阅读版本 0.0.35基于WXT 0.20、Vue 3、TypeScript 与 pnpm构建同时产出 Chrome/Edge MV3、Firefox MV2 扩展与 userscript 独立发布出口。与简单移动文件的重构不同本文描述的架构目标是建立可由编译、单测、功能测试和真实浏览器回归持续验证的模块边界见 docs/architecture.md。技术栈可从 package.json 直接印证wxt^0.20.18、vue^3.5.13、typescript^5.7.3、dexie^4.4.4缓存与配置持久层、element-plus^2.9.3设置界面、crypto-js缓存键与凭据摘要、defuddle页面正文提取等Node 引擎要求20包管理器固定为pnpm9.12.1。设计目标七条原则架构文档开篇给出了七条核心目标它们决定了后续所有目录与依赖决策入口薄WXT entrypoint 只声明 manifest 选项、绑定生命周期并组装模块不承载业务逻辑。业务聚合单词本、划词、悬浮、图片、视频等功能各自拥有协议、运行时、UI 和测试形成纵向切片。核心可测翻译算法、候选发现、文本识别、语言与热键规则尽量保持纯函数便于无浏览器环境测试。边界可执行core、provider、feature 内部与 WXT 入口等关键依赖方向由 fitness tests 约束对应 tests/architecture/moduleBoundaries.test.ts。静态插件化各运行上下文使用静态注册表兼顾 WXT 构建、MV2/MV3 与 tree-shaking。渐进迁移旧路径保留带deprecated标记的兼容导出每次迁移都能独立编译和回归。开源友好目录、公共入口、注释、测试命令和扩展方式对新贡献者可发现、可复现。与 Go 项目的分层对应为了让熟悉后端分层的开发者快速定位文档把 FluentRead 目录与 Go 项目中的典型概念做了映射FluentReadGo 项目中的近似概念职责entrypoints/cmd/*WXT 文件式入口与运行时启动src/app/application bootstrap组装 feature、消息路由和生命周期src/features/业务 package用户可感知的纵向功能src/core/纯领域 package算法、类型、不可变规则src/services/use case/service跨 feature 的应用编排src/providers/interface implementation翻译厂商和外部服务适配src/platform/infrastructure/syscall wrapper浏览器、存储、offscreen、网络边界src/shared/小型公共 package无业务语义、无副作用的通用工具src/ui/UI kit跨 feature 复用的 Vue 组件与设计 tokenuserscript/、测试 runner外部进程/插件独立发布出口、Harness 与第三方集成边界目标目录结构文档给出完整的目标目录树当前仓库已基本按此落地entrypoints/ # WXT 只发现这里的入口 background.ts content.ts popup/ options/ document/ offscreen/ *.content.ts src/ app/ background/ # 静态 message handler registry content/ featureRegistry.ts # content feature 生命周期契约 featureLifecycle.ts popup/ options/ document-translation/ offscreen/ features/ full-page-translation/ hover-translation/ selection-translation/ services/ edgeTtsPolicy.ts # 音色、SSML、UTF-8 分段与 token 时效纯规则 edgeTts.ts # Web Crypto、网络与取消边界 wordDictionary.ts # 词条归一化、开放数据 provider、缓存与并发去重 input-translation/ floating-ball/ vocabulary/ document-translation/ core/ # 格式识别、结构解析、渲染与安全预览 services/ # 二进制读写和可注入的翻译编排 ui/ # 纯展示模型与 PDF Canvas 浏览器适配 image-translation/ area-translation/ video-subtitle/ site-rules/ settings/ core/ translation/ # 纯翻译/候选/序列化算法 language/ hotkey/ site-rules/ services/ translation/ broker.ts # provider 调度、pending 去重、摘要编排 cache.ts # 翻译缓存 context/ # 页面上下文纯策略与 Defuddle/DOM 适配 legacyPageCache.ts # 仅迁移 FluentRead 自有旧缓存键 queue.ts config/ # 配置读取、迁移、写入协调 providers/ translation/ registry.ts microsoft.ts google.ts deepl.ts ai-sdk/ ... platform/ browser/ storage/ offscreen/ http/ shadow-ui/ shared/ dom/ function/ geometry/ image/ ui/ components/ styles/ tokens.css view-model/ userscript/ # 独立发布出口复用 core/service/provider tests/ *.test.ts # 由 test-matrix 唯一归入 unit/functional/regression architecture/ # 架构 fitness tests test-matrix.json文档特别强调旧的entrypoints/utils/兼容层已经删除业务代码和测试必须直接依赖src公共契约不能重新创建入口工具目录、components/Main.vue或巨型 entrypoint。从仓库现状看entrypoints/ 下只有薄入口文件如 background.ts、content.ts业务组装全部下沉到 src/app/ 与 src/features/。依赖方向硬规则与兼容债务架构文档用一张 ASCII 依赖图定义了目标方向entrypoints | v src/app --------- src/features --------- src/services --------- src/providers | | | | | ------- src/core ---- | | | | ----------------------------------- src/platform ---------------- | v src/shared src/ui 只能依赖 feature 的公开 view-model/contract、core 类型和 shared。 外部 Harness 或本机 bridge 通过版本化协议与 extension 通信不能被扩展运行时代码反向依赖。对应的硬规则不可协商src/core/**不得 importentrypoints、Vue、WXT、browser API、feature 或 platform。src/shared/**不得 import 任何业务层。feature 不得 import 另一个 feature 的内部文件确需协作时通过公开 contract 或 service。provider 只处理供应商协议不直接操作 DOM、Vue、配置页面或 runtime message。entrypoint 不直接 import feature 内部实现只 import app composition root。禁止新增跨层循环依赖。兼容 re-export 只能位于明确的迁移白名单并带deprecated。这些规则不是纸面约定而是被 tests/architecture/moduleBoundaries.test.ts 用 TypeScript AST 强制执行的该测试递归读取仓库源码/\.(?:cts|mts|ts|tsx|vue)$/用ts.createSourceFile解析每个文件的 import/export 说明符含import()动态导入与 import type再按模块边界断言方向合法性。因此依赖方向可执行在 FluentRead 中是字面意义上的——边界违反会直接让pnpm test:architecture失败。文档同时诚实指出当前仍有少量 feature 通过src/app/translation客户端或 background router 类型复用应用层契约它们不形成循环关键 provider/core/跨 feature 边界已受测试约束但仍是后续下沉 public port的迁移债务依赖图是目标方向不代表所有历史调用已经完全单向。WXT 边界构建输入、静态注册与运行时约束WXT 会把entrypoints/下零层或一层的入口作为构建输入并在构建阶段于 Node 环境导入 TypeScript entrypoint因此架构文档给出以下约束background/content 的浏览器运行时代码必须放在main()内或放在被main()调用、且模块顶层无浏览器副作用的模块中。不使用运行时扫描目录或未知动态 import 自动发现 feature。background、content、popup/options、offscreen 分别拥有静态注册表不能创建一个把全体上下文代码打进同一 bundle 的万能 barrel。content 及仅含 popup/options/unlisted-page 的构建组把配置存储解析为远端运行时Dexie、加密仓库和旧配置迁移由 background 持有包含 background 的构建组不做替换保留 Firefox MV2 后台页面的数据库能力。非中文界面语言包作为i18n/lang.json按需 fetch不进入 content 主包内容脚本不能import()以use_dynamic_url暴露的扩展脚本动态 ID 不满足隔离环境script-src self固定地址又会让网页探测扩展因此 Defuddle 随内容脚本打包。这一条在 wxt.config.ts 中有完整的实现证据remoteConfigStorageBuildPlugin通过resolveId把非后台构建组的configStorageRuntime替换为remoteConfigStorageRuntime.tscreateExtensionManifest按resolveBrowserCapabilities(env)动态决定是否声明offscreen权限CSP 固定为script-src self wasm-unsafe-eval; object-src self;web_accessible_resources只暴露图标与UI_LANGUAGE_BUNDLE_DIRECTORY/*.json且启用use_dynamic_url: true。其余关键约束Options 性能首次只挂载当前设置分区访问后的分区保留实例和编辑状态学习中心与设置表单的KeepAlive必须使用不同缓存键表单挂载前等待配置和界面语言就绪避免默认值闪现与额外重渲染Popup/Options 按实际使用的 Element Plus 组件引入样式。ONNX/WASM 打包ONNX Runtime 的 WASM 随扩展以原始.wasm保存由发布 ZIP 统一压缩Edge Partner Center 拒绝包内嵌套.gz首次模型初始化时读取并校验 WASM 后注入env.wasm.wasmBinary静态 MJS 仍从扩展自身加载CPU 与 WebGPU 共用入口成功或失败后释放注入的二进制引用。OPUS/Whisper 使用 ORT 1.22 的 JSEP pairKokoro 使用 ORT 1.26 的 Asyncify pair两者不能混用版本或 WASM/MJS 类型wllama 是另一套独立引擎。wxt.config.ts的build:publicAssets钩子正是把ort-wasm-simd-threaded.jsep.*、tts-ort-wasm-simd-threaded.asyncify.*与wllama.wasm分别打包的落点。MV3 service worker内存状态必须允许重启需要持久化的数据进入 storage/IndexedDB。扩展自有 DOM 运行时由 background 管理content 和 UI 只通过类型化消息协议请求能力。Chrome/Edge MV3 用原生 OffscreenFirefox MV2 用后台页面中的隐藏扩展 iframe两者加载同一个offscreen.html复用同一份消息路由、OCR、图片/区域绘制、字幕推理和 TTS 播放逻辑。extensionDomClient只选择文档容器并共用createOffscreenClient的准备、握手、截止时间、取消和重建Firefox 特有代码只负责 iframe 创建、查询与移除不另写 feature handler、算法或配置。offscreenDocument仅表示原生 API 与权限extensionDom表示共享运行时可用Firefox 的图片、区域、本地字幕和扩展朗读可用但 Chrome Translator 单独受chromeTranslation能力约束Firefox MV3 尚未开放此适配。content 生命周期使用 WXTContentScriptContext与AbortSignal扩展失效后不得继续回写页面默认关闭的输入翻译和段落复制不挂载监听器由独立子 signal 随配置启停图片悬浮的连续 pointermove 每帧只检测最新事件关闭和卸载时取消待处理帧。单文件还是目录决策标准文档给出可操作的分流标准。单文件适合同时满足以下条件的能力只有一个清晰职责不跨 background/content/UI 等运行上下文没有独立协议、样式或持久化模型文件仍容易阅读和完整单测。典型例子是翻译缓存先以src/services/translation/cache.ts单文件存在无需为了形式建空的 repository/model 子目录。出现任一情况则应建 feature 目录同一能力跨两个以上运行上下文同时包含 domain、协议、运行时、Vue UI 或 CSS有独立持久化模型和迁移需要多个贡献者并行维护单文件已混合多种变化原因。同时有一条硬性禁令禁止使用common.ts、misc.ts、helpers.ts作为新垃圾桶通用函数应按语义进入shared/text、shared/time等小包。Feature 结构复杂功能按需子目录复杂 feature 采用按需子目录不创建空目录文档以单词本为例给出结构src/features/vocabulary/ domain/ entry.ts reviewSchedule.ts application/ vocabularyService.ts background/ handlers.ts content/ selectionAction.ts ui/ VocabularyBook.vue vocabularyBook.css protocol.ts index.ts README.md较小 feature 保持扁平src/features/hover-translation/ content.ts rules.ts hoverTranslation.css index.ts每个 feature 通过public.ts、protocol.ts或明确的领域出口公开 API内部文件可以互相 import外部模块只能从这些公开契约导入。从仓库现状看src/features 下 20 个 feature 均符合这一模式如 src/features/vocabulary 有 7 个.ts与 2 个.vuesrc/features/hover-translation 保持 2 个.ts的扁平结构。插件契约静态注册 运行时生命周期文档明确插件化是编译期注册 运行时生命周期不是通用 IoC 容器。content feature 的最小契约interface ContentFeatureDefinition { id: string isEnabled(): boolean mount(runtime: ContentFeatureRuntime): void | Promisevoid unmount?(): void isMounted?(): boolean }运行时负责五项工作检查 feature 是否启用及激活是否仍有效按静态注册顺序挂载隔离单个可选功能的失败不让它阻断后续功能激活失效时反向卸载释放 DOM、listener、timer、observer 和 pending session对异步 UI 做所有权校验避免旧请求回写新页面。该契约在 src/app/content/featureRegistry.ts 中有逐行对应的实现ContentFeatureRegistry.reconcileEnabled()先在任何异步等待前释放已关闭或能力不支持的功能再按isFeatureDesiredrequiredCapability能力门控 isEnabled()逐个挂载performFeatureMount通过ensureContentFeatureMounted对带isMounted的异步 UI 做重试与所有权复验迟到挂载必须复验 activation 与最新配置不能复活已关闭功能单个 feature 抛错只走onError记录并返回{status: failed}unmountAll()按反向顺序卸载让后挂载的覆盖层先释放监听器和 DOM。这正好印证了文档中隔离失败 反向卸载的运行时职责。background 使用独立的类型化 handler 契约interface BackgroundMessageHandlerTMessage, TResult { type: TMessage[type] parse(value: unknown): TMessage handle(message: TMessage, context: BackgroundContext): PromiseTResult }handler registry 必须静态 import。每个 feature 保存自己的 protocol 与 handlerapp/background只负责注册、分发和统一错误序列化。src/app/background 下的handlers/translation、imageTranslation、areaTranslation、vocabulary、modelUsage 等 17 个 handler与messageRouter.ts、messageRuntime.ts正是该契约的落地handler.type作为 discriminated union 的判别字段parse保证 payload 可解析杜绝any穿透。翻译链路broker 编排与缓存策略文档给出的目标调用链feature - translation service public API - broker (凭据校验、上下文、pending 去重、缓存) - provider registry - provider adapter - platform/http链路约束翻译算法与 DOM 候选发现不读取 provider 配置。provider 不直接读 UI 状态。缓存 key 必须包含会改变结果的 service、model、endpoint、语言、prompt/context 与 transport profile。background 与 userscript 共用同一 broker不维护两份相似实现。cache 失败只能降级为未命中不能让翻译功能整体失效。broker 实现src/services/translation/broker.ts 是后台翻译用例的中心服务注释明确其职责为编排翻译请求的配置快照、语言解析、缓存、请求去重、超时与 provider 调用。源码常量给出了可核对的数量级DEFAULT_PROVIDER_TIMEOUT_MS 45_000单请求默认 45 秒超时、PAGE_SUMMARY_CACHE_SIZE 8、PAGE_SUMMARY_LIMIT 1200。它同时支持单条、批量和页面摘要三种模式验证 provider 返回数量和类型对完整多段协议逐槽修复上下文回显以包含 Chrome auto 检测样本的完整身份构建缓存键并按匿名额度身份、等待策略、清理代次与剩余 deadline 隔离 pending 请求。provider registrysrc/providers/translation/registry.ts 是查找适配器的唯一目录分为三组传统 REST 与机器翻译myMemory、microsoft、freeTranslation、deepL、deeplx、google、xiaoniu、youdao、chromeTranslator、tencent、googleCloudTranslation、azureTranslator、aliyunTranslation、baiduTranslation、volcTranslation、大模型翻译tongyi、zhipu、gemini、claude、deepseek、hunyuan、localTranslation、AI SDK 兼容服务AI_SDK_SERVICE_IDS批量绑定translateWithOpenAICompatibleAiSdk。例外是 Azure OpenAI 在进入共享 transport 前保留自身 endpoint/key 校验豆包按模型分流翻译专用模型只在 Responses API 上提供。provider 适配层只把统一翻译请求转换为外部或浏览器服务协议缓存、去重和超时总预算由 broker 统一协调。缓存策略与 Dexie 持久层缓存是文档着墨最多的部分参数在 src/core/config/translationCache.ts 与 src/services/translation/cache.ts 中双重印证翻译结果缓存默认上限 10,000 条、10 MiB10 × 1024 × 1024 字节任一达到上限先清理过期项再按 LRU 淘汰有效期为24 小时。可调范围条目数 10010,000字节数 1 MiB10 MiBMIN/MAX_TRANSLATION_CACHE_MAX_*非法值恢复默认有限数值取整并收敛到支持范围超出新上限的旧配置自动收敛。容量统计为UTF-8 键与译文之和TextEncoder.encode().byteLength不包含数据库记录与索引开销不能视作磁盘占用硬上限。增量更新在事务内汇总Dexietotals表读取按键查询内存热层最多 128 条命中访问时间只作为 LRU 排序提示短窗口TRANSLATION_CACHE_TOUCH_FLUSH_MS 32ms内合并为一次 bulkGet/bulkPut 事务在依赖 LRU 顺序的写入和维护前先落盘已清空、替换或删除的记录不会被写回。缓存键为版本化 sha256canonicalize()对结构化身份做确定性序列化对象字段排序、数组/字符串/数字分别编码buildTranslationCacheKey拼上TRANSLATION_CACHE_VERSION 3后取摘要得到v3:hex形式的不可读 key。版本号允许未来修改缓存协议而不会误用旧数据。缓存经 Dexie 存入扩展 IndexedDBFluentReadTranslationCache库entries/totals两张表browser.storage只承载容量配置不承载整份翻译结果。单条记录上限 256 KiBTRANSLATION_CACHE_MAX_ENTRY_BYTES。Chrome storage.local 的 10 MB 配额不等同于 IndexedDB 配额扩展已有unlimitedStorage权限但磁盘不足仍可能使写入失败容量扩大不需要增加权限缓存写入失败时仍继续翻译。MV3 重启后仍需复用的数据进 IndexedDB仅请求内去重保存在内存。动态页面的翻译稳定性悬浮与全文翻译共用候选、节点状态和渲染链路稳定性由手势、请求、提交和 DOM 所有权四层保证不能只靠防抖延长等待时间手势有效性按键集合必须与当前配置精确匹配部分释放期间不再响应移动额外按键、选区接管、失焦或卸载取消当前悬浮手势被取消的组合不能在下一次鼠标移动时自行恢复。请求复用相同请求按完整调用身份去重共享结果的等待者仍保留自己的取消和截止时间页面路由提交代次与内容缓存代次分开过期结果不能回写新页面。提交校验异步返回后同时检查当前 owner、generation、候选资格及每个文本槽的原文Text 对象相同或整段拼接原文相同都不足以证明结果有效等价 Text 重建可以重绑但必须同步更新恢复原文的快照并使用当前空白前后缀。DOM 所有权MutationObserver 根据精确目标和最后写入值识别扩展自己的事务同值属性写入是无操作后代的 class/style 改动不能拿祖先快照抵消真正的原文、保护区或候选资格变化仍会失效并重新发现。其他翻译器共存页面已有译文节点及其直属原文单元作为外部翻译边界正文与全部节点范围都避免叠加译文该边界进入来源与提交校验后出现的外部译文会使 FluentRead 释放自身译文移除后活动全文会话可重新发现原文快照省略被接管的单元恢复只清理 FluentRead 工件notranslate术语、代码与未翻译的相邻段落不受影响。原文保全仅译文的轻 DOM 槽保存宿主原文宿主克隆槽后丢失闭合 ShadowRoot清理必须先解包原文再删除失去所有权的容器不能拆掉其他活动翻译拥有的槽。展示稳定性等价双语重挂按来源、结构和译文工件验证后接管鼠标高亮只改变绘制不改变布局与宿主持续争抢 DOM 时用已有修复预算收敛避免无限恢复和重译。文档特别提醒回归需同时断言请求数、工件唯一性、原文恢复、迟到结果隔离和连续帧可见性缓存命中导致请求数不增仍可能发生 DOM 闪切。配置与消息三层存储与迁移协议配置分三层职责边界清晰core/config类型、默认值、纯 normalize/validate/migrate如 src/core/config/translationCache.ts 的normalizeTranslationCacheLimits就是纯函数。services/configlatest-write-wins、历史记录、保存队列、凭据协调。platform/storage后台专属加密 IndexedDB、旧 WXT storage/会话凭据迁移与跨上下文只读代理。首次读取协议后台首次读取先检查 IndexedDB 的local:config主记录存在则直接解密使用完全不再读旧 storage只有主记录不存在时才加载旧配置、原子写入并读回验证 IndexedDB成功后清理旧键。加密清理标记的检查优先于主记录因此仅含历史或凭据的旧快照在清理中断后也只恢复既有迁移不会重新扫描残缺旧 storage 或删除已成功迁入的记录。若旧快照没有主配置标记在清理完成后仍作为 durable authority 保留到默认主配置建立保证并发事务检查期间不会同时缺少主记录和标记。并发安全迁移在同一个写事务内再次检查主记录只允许一个完整旧快照胜出避免并发后台把不同快照的配置、历史和凭据逐键拼接迁移记录与待验证加密清理标记同事务提交该阶段只为持久记录保存内容摘要会话凭据只做 AES-GCM 认证不在持久标记中保留普通摘要。读回成功后先把标记改为只含实际待删键的已验证状态再开始删除旧载体清理被后台退出打断或配置随后变化时后续启动仍按已验证键幂等删除绝不重新读取或回灌旧 storage全部删除成功后再清除标记。写入协议扩展页面提交整份配置必须通过 background 的 mutation coordinator不能在 popup、文档页或 content 上下文直接写配置记录翻译计数用独立增量消息最近的 operationId 与 count 放在同一存储记录中原子提交但不进入配置历史、导出文件或运行时 UI 对象后台保存普通配置时公开配置、持久凭据、历史脱敏和旧会话凭据清理会先完成加密再通过同一个 IndexedDB 事务提交避免后台在多条记录之间退出时留下新旧状态混合。userscript 计数userscript 没有跨站点共享的原子后台因此计数采用每个顶层文档独占的单调 GM 副本总数等于迁移基数加所有副本绝对值local:config.count只是可重建的显示投影热路径只写当前副本启动、页面重新可见和打开设置时才聚合全部副本经典 GM API 没有 CAS不能在保持跨标签精确性的同时安全自动压缩旧副本因此不得用有竞争的读改写优化掉这些键。消息协议消息必须使用版本化、可解析的 discriminated union禁止在多个 feature 中散落同名字符串和anypayload隐私或本机 bridge 协议还必须定义大小上限、TTL、URL 清洗、错误码和 stale-version 防护。CSS 与 Vue 的放置规则全局颜色、间距、层级进入src/ui/styles/tokens.css仓库中对应 src/ui/styles 下的设计 token 体系。extension page 的布局样式跟随对应 page/feature。content overlay 的 CSS 跟随 feature并继续通过 Shadow DOM 或 WXT UI 工具隔离。可复用无业务组件进入src/ui/components只服务一个 feature 的组件留在 feature 的ui/。Vue 页面只负责组合和交互不直接实现翻译、存储或消息业务规则。注释规范文件级契约与 step 注释文档对注释有强约束src/下的 TypeScript、Vue、CSS 与 Markdown 文件必须从第一个字符开始提供可独立阅读的文件级长注释统一写明精确的file相对路径、文件职责、主要内容与模块边界职责解释文件解决的问题主要内容列出它维护的关键类型/流程/UI模块边界说明允许依赖和不得承担的职责。Vue/Markdown 用 HTML 注释TypeScript/CSS 用 TSDoc 风格块注释职责变化时必须同步维护禁止复制不含文件语义的占位模板。非平凡编排函数使用有意义的 step 注释async function runTranslation(): PromiseResult { // Step 1: 校验输入并创建本次请求的所有权标识。 // Step 2: 读取缓存命中时直接返回。 // Step 3: 调用 provider并在仍持有所有权时提交结果。 }规则是解释为什么、边界和所有权不复述语法——不为一行 getter、显然的类型守卫或简单映射机械添加 Step 1导出的公共契约需要 TSDoc临时兼容导出必须标注deprecated与新路径。这一规范被 tests/architecture/sourceFileHeaders.test.ts 以架构测试的形式固定下来仓库中每个src/文件如 src/app/content/featureRegistry.ts、src/services/translation/cache.ts开头的注释块都是该契约的直接实例。测试契约四层分类与双 100% 门槛测试分为四层由 tests/test-matrix.json 唯一归入unit纯函数、状态机、parser、cache identity、feature registry、provider request builder。functional多个真实模块协作但替换网络、浏览器或时间边界。regression每个历史 bug 至少一个最小复现名称说明过去的失败条件。browser隔离的真实 Edge/Firefox 验证 manifest、WXT 生命周期、DOM、Shadow UI、快捷键与跨页面行为。覆盖率采用两部分且都必须达到 100%可执行代码覆盖纳入测试边界的 TypeScript 业务代码在 statements、branches、functions、lines 四维均为 100%pnpm test:coverage即vitest run --config vitest.coverage.config.ts。仓库验证归属覆盖每个被排除于 V8 覆盖率的 entrypoint、Vue、CSS、HTML、兼容 shim 或浏览器脚本都必须在清单中拥有构建、组件测试、静态契约或真实浏览器测试不能存在未分类文件对应 tests/architecture/verificationOwnership.test.ts。文档明确禁止通过新增v8 ignore、排除难测业务代码或无断言执行制造 100%——正确做法是先把 entrypoint/Vue 中的业务逻辑抽到可测模块再扩大严格覆盖范围。测试命令目标与 package.json 的 scripts 对应pnpm test:unit # 精准单测 pnpm test:functional # 功能测试 pnpm test:regression # 历史回归 pnpm test:coverage # 四维 100% 门槛 pnpm test:regression:all # 一键确定性流水线静态检查、测试、构建与文档 pnpm test:regression:all -- --browser # 追加屏幕外隔离浏览器 fixtures自动测试审计scripts/testing/audit-test-suite.mjs检查矩阵漏项/重复归类、重复 suite/case 名、.only、无说明的.skip和 coverage ignore pragmamock 是否停留在外部边界、静态源码契约是否需要补行为测试继续由 code review 与 verification ownership 审计共同负责。迁移顺序与变更规则迁移清单用于区分本轮已验证结果与仍需偿还的历史复杂度当前状态为建立重构前测试、TypeScript 与 Chrome MV3 构建基线固化目标目录、依赖方向、WXT 与插件契约建立架构 fitness tests、覆盖率边界清单和一键测试入口合并 background/userscript 的翻译 broker 与缓存实现拆分 background typed message router拆分 content feature composition root迁移配置、provider、platform 与 shared迁移全文、悬浮、划词、输入框、单词本、文档、图片、区域和视频 feature拆分 WXT 页面 composition、主要 Vue 页面和 feature CSS全量单测/功能/回归、Chrome/Firefox/userscript 构建、文档构建在屏幕外隔离 Edge 完成六组确定性 fixture 功能验收真实 Firefox 与真实网络站点矩阵作为独立后续门禁不由本轮 Edge fixture 替代下游调用迁移完成后删除兼容导出当前兼容集合由架构测试精确锁定完成本轮逐条需求审计每个迁移批次必须遵守六条变更规则保持旧公开行为或同批次更新产品文档增加或迁移对应单测历史 bug 保留回归用例运行目标模块测试、pnpm compile、git diff --check涉及入口、manifest、offscreen 或样式时运行对应浏览器构建不在同一批次混入无关功能改动在 PR 描述中列出迁移前后路径、兼容层、验证证据与剩余阶段。阅读助手 Harness 核心有界 ledger 与只读工具阅读助手采用浏览器内的有界 ledger 和独立工具循环参考 DeepSeek Harnessdsh-v0.1.3-alpha.1commitd347e703908d0406b7a7ef80e3a0e594d86b2215的packages/core/session/src/surface.ts消息投影思想。FluentRead 只保留选区、已授权段落、追问历史和只读read_context工具不引入上游桌面 host、bridge、Cordis、插件、文件系统、进程、沙箱或动态执行能力模型仍由现有 AI SDK gateway 选择兼容模型与原生 Anthropic/Google 模型均通过各自协议接入不能假设任意模型都支持工具调用或流式输出。阅读卡通过fluentReadHarnessStreamport 接收模型、正文和会话进度正文按模型返回的增量快照更新停止、错误、关闭、换选区和 worker 中断会取消当前请求已收到正文仍保留在卡片中。普通模式的会话按问答保存在本机 30 天历史可从阅读卡或设置页折叠查看、恢复、删除和清空恢复只加载已有 turns不自动发起模型请求后台重建上下文时最多使用最近四轮隐私窗口不保存也不读取历史。小结架构的可验证性FluentRead 架构的核心价值不在于目录长得漂亮而在于每条边界都有对应的强制检查依赖方向由 tests/architecture/moduleBoundaries.test.ts 的 AST 依赖图锁定provider 边界由 tests/architecture/providerBoundaries.test.ts 锁定文件级注释由 tests/architecture/sourceFileHeaders.test.ts 锁定覆盖率归属由 tests/architecture/verificationOwnership.test.ts 锁定。新贡献者接入时应先阅读本文与 docs/architecture.md再对照 src/ 现有 feature如 src/features/vocabulary、src/features/hover-translation理解静态注册 运行时生命周期的写法最后用pnpm test:architecture与pnpm test:regression:all验证改动没有破坏任何既定边界。赞分享前端AI 应用本地部署【免费下载链接】FluentReadAn open-source browser extension for bilingual translation. 一款开源的浏览器双语翻译插件。项目地址https://gitcode.com/gh_mirrors/fl/FluentRead点击查看免费下载相关推荐vscode-wakatime高级技巧自定义API URL、代理设置与团队协作功能vscode wakatime高级技巧自定义API URL、代理设置与团队协作功能 vscode wakatime是一款强大的Visual Studio CoDBX Rust crates 工作区架构全解12 个模块化 crate 的职责划分、依赖边界与构建验证DBX Rust crates 工作区架构全解12 个模块化 crate 的职责划分、依赖边界与构建验证 本指南以 crates/README.md http数据库开发者工具桌面应用CLIMCP 服务AI 应用StarRocks CacheStats Connector 解析_CACHE_STATS_ 查询提示背后的模块架构与依赖边界StarRocks CacheStats Connector 解析_CACHE_STATS_ 查询提示背后的模块架构与依赖边界 本文基于 StarRocks数据库OLAP数据仓库大数据湖仓一体数据分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。