
DeerFlow 前端性能基线与交付路由资源预算门禁、安全压缩、懒加载图片与静态 Demo 清单【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow本文基于 DeerFlow 仓库中的前端性能基线交付计划plans/2026-07-31-frontend-performance-baseline-delivery.md系统讲解四项落地措施可复现的路由资源预算门禁、Nginx 文本响应安全压缩、落地页案例研究图片懒加载以及用显式清单替代请求期文件遍历的静态 Demo 数据访问。读完后你将理解这套性能门禁的度量原理、预算文件结构与验证方式并能将同样的“测量—预算—回归证明”流程套用到自己的 Next.js 项目中。1. 计划总览把性能发现变成可重复的交付门禁该计划的核心目标Goal是把此前对路由权重route-weight与交付链路delivery的人工发现转化为可重复执行的门禁gates同时启用安全的压缩、消除落地页案例研究图片的立即下载eager download并移除 mock 路由对“整个项目”的意外追踪trace。计划的架构分工Architecture明确了四个“所有权”生产服务器度量脚本负责路由资源核算route asset accounting并与一份签入仓库的预算文件比对Nginx负责文本类响应的压缩textual response compression落地页图片改为语义化的懒加载图片semantic lazy images静态 Demo 数据通过显式清单explicit manifest暴露路由处理器route handlers不再从请求输入推导文件系统路径。技术栈为 Next.js 16、TypeScript、Rstest、Node.js、Nginx、pnpm。计划还设定了四条全局约束保持现有 API 路由不变绝不压缩 SSE 或已压缩的媒体每个修复都遵循 RED先写失败测试→ GREEN实现至通过→ 回归证明revert 后证明测试会失败→ 提交 的纪律所有预算调整必须基于实测而不是为了让门禁通过而放松上限。下文按计划的四个 Task 展开并结合当前仓库中已落地的源码与测试说明每项措施的实现细节与验证依据。2. Task 1可复现的路由资源预算门禁2.1 度量脚本从 HTML 到字节数计划要求新建的度量脚本对应 measure-route-assets.mjs。它的运行流程在源码中可以完整印证构建以pnpm exec next build构建生产包脚本中的createBuildEnvironment负责在“静态 Demo 模式”下注入NEXT_PUBLIC_STATIC_WEBSITE_ONLYtrue否则删除该变量L24-L35启动在127.0.0.1上通过getFreePort申请空闲端口spawn启动next start并用waitForServer轮询30 秒超时等待服务就绪L125-L140测量对每条路由fetch其 HTML用extractAssetPaths从src/href属性中解析出/_next/static/前缀下的 JS/CSS 文件同一文件只计一次seen集合去重再对.next/static下对应文件stat求和得到字节数同时记录 HTML 自身字节数L40-L60、L142-L157输出与比对完整结果写入.next/performance-results.json并打印到 stdout--check模式下读取预算文件调用evaluateBudgets逐路由、逐资源类js/css比较任何超限都会抛出包含路由、资源类、实际字节数与上限的失败信息L62-L79、L209-L237。脚本还导出纯函数extractAssetPaths(html)与evaluateBudgets(measurements, budgets)供单元测试覆盖——计划 Task 1 明确要求先为这两个导出函数写失败测试断言重复脚本只计一次、超限 1 字节即失败并报告路由/资源类/实际字节/上限。值得注意的实现细节是双模式测量main()先用普通生产构建测量/login再在静态 Demo 模式NEXT_PUBLIC_STATIC_WEBSITE_ONLYtrue下测量其余路由并把每条测量结果标记buildMode: static-demo | normalL209-L217。这对应 DeerFlow 前端的静态演示场景工作区路由/workspace/chats、演示线程由 fixture 数据驱动只有静态构建才能稳定复现其资源集合。被测量的路由列表定义为/、/login、/workspace/chats、/workspace/chats/7cfa5f8f-a2f8-47ad-acbd-da7137baf990规范演示线程、/en/docs、/blog/postsL11-L18。2.2 预算文件计划初始上限 vs 当前签入基线计划要求签入的初始上限全部低于当时实测基线如下路由JS 上限计划初始值CSS 上限计划初始值/1,050,000150,000/workspace/chats2,750,000150,000演示聊天demo chat3,500,000150,000/en/docs、/blog/posts3,000,000230,000当前仓库中实际签入的 performance-budgets.json 如下{ /login: { css: 170000, js: 850000 }, /: { css: 175000, js: 1050000 }, /workspace/chats: { css: 190000, js: 1750000 }, /workspace/chats/7cfa5f8f-a2f8-47ad-acbd-da7137baf990: { css: 190000, js: 4100000 }, /en/docs: { css: 270000, js: 4200000 }, /blog/posts: { css: 270000, js: 4200000 } }从源码结构看当前基线与计划初始值存在系统性差异新增了/login路由对应脚本的双模式测量CSS 上限普遍上调/workspace/chats的 JS 上限从 2,750,000 收紧到 1,750,000而演示聊天与文档/博客页的 JS 上限反而放宽到 4,100,000/4,200,000。这与计划中“初始上限仅为占位、最终门禁推迟到 bundle 计划落地后再定”的表述一致——可以推断这些数字是后续实测校准后的回归基线。计划对此有一条硬性纪律也被写进了 frontend/AGENTS.md预算超限时修复路由归属或代码分割点没有文档化并经评审的实测回归不得抬高上限。2.3 接入工程命令门禁通过 npm script 暴露见 package.jsonperf:check: node scripts/measure-route-assets.mjs --check运行方式即cd frontend pnpm perf:check计划要求的验证闭环是先把/的 JS 预算临时改为1证明pnpm perf:check会失败RED再恢复文件把最终通过推迟到 bundle 优化落地。AGENTS.md 中对该命令的说明与脚本实现完全吻合测量/login普通构建与 fixture 驱动的工作区路由静态 Demo 构建、在临时本地端口启动生产服务器、测量代表路由引用的去重 JS/CSS 文件、写.next/performance-results.json、与performance-budgets.json比对。3. Task 2启用安全的 Nginx 压缩3.1 压缩策略只压文本不碰 SSE 与已压缩媒体计划要求在两份 Nginx 配置Docker 版与本地开发版的http块加入完全一致的压缩指令包含gzip_proxied any且绝不加入通配 content type。当前仓库中两份配置均已落地docker/nginx/nginx.conf# Compress textual delivery only. SSE and already-compressed media are # deliberately absent because buffering/compression hurts their latency. gzip on; gzip_vary on; gzip_proxied any; gzip_min_length 1024; gzip_comp_level 5; gzip_types text/css text/javascript application/javascript application/json application/xml image/svgxml;docker/nginx/nginx.local.conf 中的指令块与之逐行相同。各指令的作用与计划中的约束一一对应gzip on/gzip_vary on开启压缩并在响应中追加Vary: Accept-Encoding保证缓存按编码区分gzip_min_length 1024小于 1KB 的响应不压缩避免小响应上的压缩开销超过收益gzip_comp_level 5压缩级别取 5默认值在 CPU 与压缩率之间平衡gzip_proxied any即使是经过代理的请求也允许压缩gzip_types白名单仅含 CSS、JS、JSON、XML、SVGHTML 由 Nginx 默认压缩无需列出text/event-stream刻意缺席——SSE 是 DeerFlow 网关与前端之间的核心流式通道nginx 配置中/api/langgraph/等 location 专门设置了proxy_buffering off与长超时以支持流式压缩会破坏其低延迟特性字体、非 SVG 图片、音频、视频同样不在列表中因为 JPEG/MP4 等属于已压缩格式重复 gzip 只会浪费 CPU。3.2 用测试固化压缩策略计划为这项配置变化编写的验证测试已落地为 test_nginx_compression.py它不依赖运行中的 Nginx而是直接解析两份配置文件并断言策略一致pytest.mark.parametrize(config_path, CONFIGS, idslambda path: path.name) def test_nginx_compresses_only_safe_textual_responses(config_path: Path) - None: config config_path.read_text(encodingutf-8) assert gzip on; in config assert gzip_vary on; in config assert gzip_proxied any; in config assert gzip_min_length 1024; in config assert gzip_comp_level 5; in config gzip_types config.split(gzip_types, 1)[1].split(;, 1)[0].split() assert gzip_types [ text/css, text/javascript, application/javascript, application/json, application/xml, image/svgxml, ] assert text/event-stream not in gzip_types assert not any(content_type.startswith((font/, audio/, video/)) for content_type in gzip_types)测试要点以gzip_types ... ;之间切出的精确列表做相等断言防止任何人悄悄加入新类型包括通配符并显式排除text/event-stream与font/、audio/、video/前缀。运行方式为cd backend uv run pytest tests/test_nginx_compression.py -q计划还要求回归证明临时回退指令块 → 证明测试失败 → 恢复 → 重新跑绿若本地有 Nginx还应启动服务并用curl --compressed -I验证 HTML 返回Content-Encoding: gzip而 SSE 响应不被压缩。最后计划要求把“Nginx 压缩文本响应但刻意排除 SSE 与预压缩媒体”写入根目录 AGENTS.md 的服务拓扑说明把这一决策从配置注释升级为团队共识。4. Task 3落地页案例研究图片懒加载4.1 问题背景图导致的立即下载落地页的案例研究区块case-study-section此前使用 CSSbackground-image渲染卡片图。背景图的请求时机完全由浏览器决定且无法携带loading等语义属性——计划发现这些图片在首屏就会被立即下载eager download浪费带宽并挤占关键资源。4.2 修复语义化懒加载图片计划要求把背景图卡片替换为带定位的next/image或原生img保留覆盖层与视觉裁切设置显式sizes只有当测量证明某图确实在初始视口内可见时才允许它 eager。当前 case-study-section.tsx 的实现印证了这一修复组件改为导入next/image图片携带完整的懒加载语义Image ... loadinglazy decodingasync sizes(min-width: 1024px) 320px, (min-width: 768px) 50vw, 100vw ... /其中loadinglazy让浏览器把视口外的 JPEG 请求推迟到滚动接近时才发起decodingasync避免图片解码阻塞主线程响应式sizes与断点布局1024px/768px 两档匹配卡片栅格。4.3 DOM 测试固化验收标准计划为这个组件设计的 DOM 测试断言了五条验收标准恰好构成一张“合格语义化图片”的检查单每张卡片都有真实的img元素而非 CSS 背景携带loadinglazy携带decodingasync有固有尺寸intrinsic dimensions防止布局偏移 CLS有描述性 alt 文本且不存在任何内联 background-image URL防止回归到旧实现。验证还要求在网络面板/trace 中确认滚动之前视口外的 JPEG 请求没有发起并做 revert 回归证明撤掉组件改动 → 测试 RED → 恢复 → GREEN。5. Task 4用静态清单替代请求期文件遍历5.1 问题mock 路由从请求输入推导文件路径DeerFlow 前端内置了一组静态 Demo 线程/workspace/chats下的演示数据其 artifacts 通过 mock 路由/mock/api/threads/[thread_id]/artifacts/[[...artifact_path]]/route.ts等服务。问题在于这些路由处理器此前在请求期用readdirSync、readFileSync、statSync从请求路径推导并访问文件系统。这带来两个后果安全隐患路径段直接参与文件系统推导存在遍历..、编码遍历风险构建问题静态 Demo 构建时Turbopack 会对这些动态文件访问做追踪触发“whole project unintentionally traced”整项目追踪告警并污染 mock artifact 的导入追踪。5.2 修复显式清单 路径段归一化校验计划要求在static-demo.ts中定义一份显式、不可变的 Demo 清单所有路径段先归一化、再校验路由处理器只能读取清单返回的路径同时把请求期同步 fs 调用替换为清单导入或fs/promises服务端执行期并保持响应负载逐字节兼容。当前 static-demo.ts 的实现正是这一方案的落地。清单是一个 threadId → artifact 相对路径列表的只读映射L24-L26并预构建为ReadonlySet加速查找。核心解析函数resolveStaticDemoArtifactL99-L128展示了完整的防御链export function resolveStaticDemoArtifact( threadId: string, encodedSegments: readonly string[], ): string | null { const allowedArtifacts STATIC_DEMO_ARTIFACT_SETS[threadId]; if (!allowedArtifacts || encodedSegments[0] ! mnt) return null; let segments: string[]; try { segments encodedSegments.map((segment) decodeURIComponent(segment)); } catch { return null; } if ( segments.some( (segment) segment.length 0 || segment . || segment .. || segment.includes(/) || segment.includes(\\), ) ) { return null; } const artifactPath segments.slice(1).join(/); if (!allowedArtifacts.has(artifactPath)) return null; return /demo/threads/${threadId}/${artifactPath}; }逐层拆解这套校验可以看到计划中“覆盖已知 artifact、未知线程、遍历段、编码遍历”四类测试用例对应的防御点攻击/异常面防御未知 threadId不在DEMO_THREAD_IDS清单中第一行allowedArtifacts为undefined返回null路径前缀不符非mnt开头首段必须严格等于mnt编码遍历如%2e%2e%2f先整体decodeURIComponent失败即拒绝再逐段检查裸遍历段.、..、空段、斜杠/反斜杠注入segments.some(...)一次性拒绝最终路径不在清单内allowedArtifacts.has(artifactPath)白名单精确匹配只有通过全部校验的请求才会被映射为/demo/threads/{threadId}/{artifactPath}这类构建期已知的静态资源路径从而让打包器只追踪清单内的文件消除“整项目被追踪”的告警。清单还配套了isDemoThreadIdSet 查表与loadStaticDemoThread(s)从/demo/threads/.../thread.json拉取 fixture 并支持sortBy/offset/limit分页语义L130-L186使 mock 路由可以完全摆脱请求期fs调用。计划要求的验收标准是运行NEXT_PUBLIC_STATIC_WEBSITE_ONLYtrue pnpm build断言之前 Turbopack 的“whole project unintentionally traced”告警与 mock artifact 导入追踪均不存在。6. 最终验证把四项修复收束成一条可重复的检查链计划“Final verification”一节定义了交付前的完整检查链它本身就是这个仓库性能回归的标准流程# 前端代码检查 单元测试 cd frontend pnpm check pnpm test # 前端路由资源预算门禁 cd frontend pnpm perf:check # 后端Nginx 压缩策略测试 cd backend uv run pytest tests/test_nginx_compression.py -q外加两项人工确认运行静态 Demo 生产构建确认零“意外文件/整项目”追踪告警把新的路由测量值记录在 PR 描述中且不得为了让门禁通过而放松任何预算。第 2 条是整个计划最值得借鉴的纪律性能门禁的价值不在于“绿”而在于预算是**只降不升除非经评审的实测回归**的资产。一旦允许随手抬高上限门禁就退化成了形式。7. 小结这份交付计划展示了前端性能治理的一个完整闭环四个 Task 分别对应四个层面度量层measure-route-assets.mjs以生产构建 生产服务器为测量环境把“路由加载了多少 JS/CSS 字节”变成可复现的数字evaluateBudgets把数字变成 CI 可执行的门禁交付层Nginx 的 gzip 白名单策略在“省带宽”与“不伤害 SSE/媒体”之间划出安全边界且用配置文件解析测试把边界固化下来渲染层next/image的loadinglazydecodingasync 响应式sizes用 DOM 测试锁定语义化图片的验收标准数据层静态 Demo 清单 路径段白名单校验同时解决路径遍历安全与构建追踪污染两个问题。对 DeerFlow 这类“长时程 SuperAgent”产品尤其有意义的是它的核心体验是流式对话SSE/WebSocket因此性能优化必须始终围绕“压缩不碰流式通道、预算不放松上限、测量不依赖开发态”三条红线展开。这套基于 plans 文档 的流程——先写失败测试、再实现、做 revert 回归证明、最后把实测值写入 PR——同样适用于任何以 Next.js Nginx 为技术栈的前端项目。【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考