资讯动态

plate 中 Slate v2 超大文档 Overlay 基准的 Readiness 硬化:面向 Next Dev 的预热与重试契约

发布时间:2026/9/17 7:50:01 来源:尧图企业网站定制
plate 中 Slate v2 超大文档 Overlay 基准的 Readiness 硬化面向 Next Dev 的预热与重试契约【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate本文聚焦 plate 仓库中 Slate v2 性能证据体系的一个具体工程问题超大文档huge-documentOverlay 浏览器基准在 Next dev 服务器环境下偶发页面未就绪导致的假失败flake。文章完整梳理该问题的症状、根因、四条硬化措施与验证流程并结合仓库内的基准目标注册表、超大文档示例与可复用学习文档给出可直接落地的基准运行器 Readiness 契约设计思路帮助你在自己的 Playwright Next dev 基准流水线中避免同类噪音。背景超大文档 Overlay 基准车道在测什么Slate v2 的 React 运行时为超大文档引入了一系列 overlay覆盖层与部分 DOM 提升promotion路径例如 overlay 开关、侧边栏隐藏/显示、overlay 之后继续输入等交互。为了把这些路径的性能证据化仓库维护了一条浏览器基准车道负责在浏览器墙钟时间内测量这些交互的开销。本仓库的 benchmarks/targets/slate-v2.json 中记录了与之对应的目标react-huge-document-overlays其问题定义是Do overlay and partial-DOM promotion paths stay local in huge documents?执行命令为bun ../../scripts/benchmarks/browser/react/huge-document-overlays.tsx工作目录位于.tmp/slate-v2/packages/slate-react产物落在.tmp/slate-v2/packages/slate-react/tmp/slate-react-huge-document-overlays-benchmark.json。在同日的另一份审计文档 docs/plans/2026-04-15-slate-v2-decoration-perf-coverage-audit.md 中可以看到这条车道代表性的测量维度与一次同轮次运行结果overlay toggleOverlay 开关均值98.12mshide/show sidebar侧边栏隐藏/显示均值97.46ms/77.45mstype-after-overlayOverlay 后输入均值15.4mstype-after-show显示后输入均值14.54msoverlay count2可见这条车道测量的不是纯核心操作而是overlay 交互 大文档 DOM 局部性的组合因此它对页面是否真正挂载完毕极其敏感——这正是本次硬化工作的切入点。本次硬化的目标与范围关联计划文档docs/plans/2026-04-15-slate-v2-overlay-benchmark-hardening.md明确了这次任务的目标Harden the huge-document overlay benchmark so the lane stops flaking on page readiness and can be trusted as perf evidence.即加固超大文档 overlay 基准使该车道不再因页面就绪readiness问题而抖动从而可以作为可信的性能证据。范围被刻意收窄为三点只处理基准运行器脚本scripts/benchmarks/browser/replacement/huge-document-overlays.mjs该文件位于外部 slate-v2 检出目录本仓库内的对应物是上文提到的react-huge-document-overlays目标只涉及该车道的 readiness / runner 契约仅在验证结论有变化时同步文档。这是一个典型的只修 runner、不碰 example的最小改动原则问题出在测量框架的等待契约而不是被测量的示例本身。症状一次看似随机的假失败该车道在一次运行中报出如下错误expect(locator(#v2-huge-blocks)).toHaveValue(1000)失败原因是控件control没有被找到。关键观察有三点同一车道不做任何代码改动、立刻重跑即通过且数字稳定服务器日志显示路由仍然返回200GET /examples/huge-document?... 200失败发生在页面预热warmup阶段而非计时采样阶段。#v2-huge-blocks定位的是超大文档示例页面中控制文档块数的输入控件期望值为1000对应块数档位。在本仓库的示例实现 apps/www/src/registry/examples/huge-document-demo.tsx 中这一控件的状态对应blocks查询参数块数档位包括2, 1000, 2500, ...直至200000。把这三个观察放在一起结论就很清晰路由返回 200 只代表 Next dev 服务端响应了请求并不代表示例 DOM 已经完成挂载。一次性的 readiness 断言把无害的预热延迟放大成了假的性能失败。根因one-shot readiness check 的脆弱契约原有运行器中的waitForCurrentReady(...)实现如下文档描述先执行两次page.goto(...)然后等待页面上的控件出现。它没有显式的重试retry也没有兜底fallback逻辑当路由先于示例 DOM 就绪返回时直接开始断言控件一旦控件尚未出现就立刻失败。根因读取root-cause read在文档中表述为the lane was relying on a brittle one-shot readiness check in a Next dev server flow where the route could answer while the example DOM was still warming or remounting.即Next dev 的流式/增量编译特性允许路由先响应而示例表面仍在 warming编译、hydration 或 remount中。此时服务端视角一切正常200浏览器视角控制控件尚未出现基准视角一次必然失败的断言。这类问题的隐蔽性在于它不具备可复现性——不修改代码重跑通常就通过因此很容易被误判为偶发的环境问题而忽略。可复用的学习记录见 docs/solutions/workflow-issues/2026-04-15-next-dev-benchmark-readiness-must-warm-and-retry-before-failing.md。硬化方案四条 Readiness 契约修复思路是加固基准运行器而不是修改被测量的示例。文档明确列出的四条硬化措施显式的就绪超时readyTimeoutMs给单次就绪等待设置上限避免无限等待有界重试readyRetries就绪检查允许重试但次数有界保证车道依然严格计时采样前先做一次预热warmup在正式计时前先访问一次路由把编译、hydration 等一次性成本排除在采样之外失败时通过about:blank重置页面再重试而不是在第一个缺失的控件上直接失败。根据文档描述可以还原出如下契约骨架示意代码非仓库原文件用于说明四条措施如何协同// 伪代码示意本硬化契约的四个组成部分 async function ensureReady(page, { readyTimeoutMs 30_000, readyRetries 3 }) { // 3) 正式计时前先预热一次把编译/hydration 成本挡在采样外 await page.goto(EXAMPLE_URL); for (let attempt 0; attempt readyRetries; attempt) { try { // 1) 单次就绪等待显式超时 await page.waitForSelector(#v2-huge-blocks, { timeout: readyTimeoutMs }); await expect(page.locator(#v2-huge-blocks)).toHaveValue(1000); return; // 就绪成功 } catch (error) { if (attempt readyRetries - 1) throw error; // 4) 重置页面避免半挂载状态污染下一次尝试 await page.goto(about:blank); await page.goto(EXAMPLE_URL); } } }第 4 条尤其关键在就绪重试之间重置页面否则一次半挂载half-mounted的尝试会污染下一次尝试——同一个 DOM 实例可能残留中间状态导致重试永远失败。为什么这组措施有效学习文档2026-04-15-next-dev-benchmark-readiness-must-warm-and-retry-before-failing.md给出了三层理由失败的本质是 runner 脆弱而非 overlay 运行时不稳定一次性的就绪断言把路由已响应、DOM 未就绪的窗口期误判为基准失败Next dev 可以路由先答、示例未稳路由成功与示例 DOM 就绪是两个独立的事件必须分开检查预热 有界重试让车道既严格又不愚蠢预热排除一次性成本重试吸收偶发延迟而readyTimeoutMs与readyRetries的有界性保证车道不会无限容忍真正的损坏。文档中的表述是 Warming once and retrying boundedly keeps the lane strict without being stupid这正是这类基准契约的设计哲学严格不等于脆弱。验证修复后的运行证据修复后的验证过程在计划文档中记录为pnpm lint:fix通过一次正常的3样本运行通过连续 5 次1样本的单次启动launch全部通过REPLACEMENT_BENCH_ITERATIONS1 pnpm bench:replacement:huge-document:overlays:local常规完整命令pnpm bench:replacement:huge-document:overlays:local通过。这里REPLACEMENT_BENCH_ITERATIONS是控制采样次数的环境变量1表示只采一个样本用于快速验证车道稳定性正常运行时使用默认3样本数。验证序列的设计意图是一长一短交替长跑验证整体健康短跑连发验证 readiness 不再抖动。仓库佐证示例与基准共享的配置契约硬化只解决了等待问题但基准要稳定示例与基准还必须共享同一个场景配置否则就会出现手动演示用一套旋钮、基准悄悄跑另一套的漂移。这一原则由 docs/solutions/performance-issues/2026-04-01-huge-document-demo-and-benchmark-should-share-a-query-param-config-contract.md 固化核心是让 Huge Document 文档页与/dev/editor-perf基准页共享同一份配置模块。从 apps/www/src/registry/examples/huge-document-demo.tsx 的源码可以看到完整旋钮及其默认值参数类型默认值说明blocksnumber10_000文档块数档位2 ~ 200_000chunkingbooleantrue是否启用分块chunkingchunk_sizenumber1000每块包含的块数chunk_divsbooleantrue每个 chunk 是否渲染为独立divchunk_outlinesbooleanfalse是否给 chunk 描边调试用content_visibilitynone/element/chunkchunk在何处设置content-visibility: autoenginesboth/plate/slateboth挂载哪些编辑器引擎selected_headingsbooleanfalse是否在每个标题调用useSelectedstrictbooleanfalseReact strict mode仅 localhost 生效其中blocks、chunking、chunk_size、content_visibility四个旋钮与基准页共享并通过createHugeDocumentBenchmarkHref生成直达/dev/editor-perf?blocks...chunking...chunk_size...content_visibility...scenario_workload...的 Open in benchmark mode 链接。而scenario_workload的取值来自 apps/www/src/app/dev/editor-perf/workloads.ts 中定义的工作负载族如huge-mixed-block每 100 块一个标题、其余为段落的原始超大文档混合负载。示例页面的公开入口是 content/docs/examples/huge-document.mdx通过ComponentPreview内嵌huge-document-demo。把这条配置契约与本次 readiness 硬化放在一起看就能得到完整的基准可信链条文档页与基准页共享同一份场景配置blocks/chunking/chunk_size/content_visibility/scenario_workload基准运行器用预热 有界重试 about:blank重置保证页面真正就绪后才开始计时计时只发生在就绪之后采样数字才能作为性能证据。预防清单给所有 Next dev 基准车道的通用经验学习文档将这次经验沉淀为可复用的预防清单适用于所有基于 Playwright 且跑在 Next dev 服务器上的基准车道把路由成功与DOM 就绪当作两个独立的检查200响应不等于示例可用必须等待真实的控件/交互点就绪重型示例路由在正式计时前先预热一次把编译、hydration、remount 等一次性成本排除在采样窗口之外车道依赖多个控件时把就绪检查当作一个整体单元重试不要在第一个缺失的 locator 上永久失败而是整组重试在就绪重试之间重置页面about:blank再回到目标路由确保半挂载的尝试不会污染下一次尝试超时与重试都要有界readyTimeoutMs与readyRetries防止车道对真正的损坏无限容忍。同一日的工作流问题还有两个相邻案例可参考docs/solutions/workflow-issues/2026-04-15-overlay-perf-coverage-must-include-annotation-widget-churn.mdoverlay 性能覆盖必须包含 annotation 驱动的 widget 抖动正确性测试不能当作性能覆盖与 docs/plans/2026-04-15-slate-v2-decoration-perf-coverage-audit.md同一轮审计中记录的同款 flake 与修复后的数字。小结这次硬化工作表面上是修一个偶发 flake实际上确立了一个可复用的基准运行器契约路由响应、DOM 就绪、计时采样三个事件必须严格分界。readyTimeoutMs给出单次等待上限readyRetries给出有界重试warmup 把一次性成本挡在采样外about:blank重置避免半挂载污染。验证证据一次 3 样本 连续 5 次 1 样本全通过表明该契约在保持车道严格性的同时消除了 readiness 噪音。对于任何在 Next dev 环境下做 Playwright 性能基准的团队这份 学习文档 与 计划文档 都是可以直接引用的工程模板基准的稳定性不是运气好而是把等待契约显式化、有界化、可重置化的结果。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价