mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-23 04:56:18 +00:00
* docs: design frontend performance remediation * docs: plan frontend performance remediation * test(frontend): add route asset performance budgets * perf(nginx): compress textual responses safely * perf(frontend): lazy load case study media * perf(frontend): bound static demo file tracing * perf(frontend): restore static locale boundaries * perf(frontend): defer closed workspace panels * perf(frontend): split editors and deduplicate highlighting * perf(frontend): index incremental message derivation * perf(frontend): stabilize paged history cache policy * perf(frontend): bound streaming markdown renders * perf(frontend): virtualize message history * perf(frontend): bound and virtualize chat lists * perf(frontend): suspend inactive decorative animation * perf(browser): stream latest frames as binary * perf(artifacts): stream bounded text previews * docs: finalize performance runtime boundaries * style(backend): apply test formatting * fix(frontend): keep translation functions client-side * perf(frontend): defer decorative animation bundles * test(frontend): lock optimized route budgets * fix: harden frontend performance boundaries * test(frontend): update i18n provider fixture * fix(frontend): preserve sidebar pagination position * style(backend): format artifact range test
85 lines
6.9 KiB
Markdown
85 lines
6.9 KiB
Markdown
# Frontend Performance Baseline and Delivery Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Turn the current route-weight and delivery findings into repeatable gates, enable safe compression, eliminate eager case-study image downloads, and remove the mock route's whole-project trace.
|
|
|
|
**Architecture:** A production-server measurement script owns route asset accounting and compares it with a checked-in budget. Nginx owns textual response compression. Landing images become semantic lazy images. Static demo data is exposed through an explicit manifest so route handlers never derive filesystem paths from request input.
|
|
|
|
**Tech Stack:** Next.js 16, TypeScript, Rstest, Node.js, Nginx, pnpm.
|
|
|
|
**Global Constraints:** Work only in `/Users/minimax/workspace/deer-flow/.worktrees/fix-frontend-performance`. Preserve current API routes. Do not gzip SSE or already-compressed media. Every fix follows RED, GREEN, regression proof, then commit.
|
|
|
|
## Task 1: Add a reproducible route-asset budget gate
|
|
|
|
**Files:**
|
|
- Create: `frontend/scripts/measure-route-assets.mjs`
|
|
- Create: `frontend/performance-budgets.json`
|
|
- Create: `frontend/tests/unit/scripts/measure-route-assets.test.ts`
|
|
- Modify: `frontend/package.json`
|
|
- Modify: `frontend/AGENTS.md`
|
|
|
|
- [ ] Write a failing unit test for exported `extractAssetPaths(html)` and `evaluateBudgets(measurements, budgets)`. Assert duplicate scripts are counted once and a one-byte overage fails with the route, asset class, actual bytes, and limit.
|
|
- [ ] Run `cd frontend && pnpm test -- tests/unit/scripts/measure-route-assets.test.ts` and record the missing-module failure.
|
|
- [ ] Implement pure helpers in `measure-route-assets.mjs`. The CLI must build with `NEXT_PUBLIC_STATIC_WEBSITE_ONLY=true`, spawn `next start` on a free local port, fetch `/`, `/workspace/chats`, the canonical demo thread, `/en/docs`, and `/blog/posts`, resolve referenced `/_next/static/` files under `.next/static`, and emit `performance-results.json`.
|
|
- [ ] Check in these initial ceilings, all below the measured baseline: `/` JS 1,050,000 and CSS 150,000; `/workspace/chats` JS 2,750,000 and CSS 150,000; demo chat JS 3,500,000 and CSS 150,000; `/en/docs` and `/blog/posts` JS 3,000,000 and CSS 230,000.
|
|
- [ ] Add `"perf:check": "node scripts/measure-route-assets.mjs --check"` and document the gate and static-demo requirement in `frontend/AGENTS.md`.
|
|
- [ ] Run the focused test GREEN. Temporarily lower the `/` JS budget to `1`, prove `pnpm perf:check` fails, restore the file, and defer the final passing gate until the bundle plan lands.
|
|
- [ ] Commit: `test(frontend): add route asset performance budgets`.
|
|
|
|
## Task 2: Enable safe Nginx compression
|
|
|
|
**Files:**
|
|
- Modify: `docker/nginx/nginx.conf`
|
|
- Modify: `docker/nginx/nginx.local.conf`
|
|
- Create: `backend/tests/test_nginx_compression.py`
|
|
- Modify: `AGENTS.md`
|
|
|
|
- [ ] Write a failing test that parses both configs and asserts the same compression policy: `gzip on`, `gzip_vary on`, minimum length 1024, compression level 5, and types limited to HTML default plus CSS, JavaScript, JSON, XML, and SVG. Assert `text/event-stream`, fonts, images other than SVG, audio, and video are absent.
|
|
- [ ] Run `cd backend && uv run pytest tests/test_nginx_compression.py -q` and capture RED.
|
|
- [ ] Add the identical directives to both `http` blocks. Include `gzip_proxied any`; do not add a wildcard content type.
|
|
- [ ] Update the service-topology note in root `AGENTS.md` to state that Nginx compresses textual responses but deliberately excludes SSE and pre-compressed media.
|
|
- [ ] Run the focused test GREEN. If local Nginx is available, start the configured service and verify `curl --compressed -I` returns `Content-Encoding: gzip` for HTML while an SSE response is uncompressed.
|
|
- [ ] Revert the directive block, prove the test fails, restore it, rerun GREEN.
|
|
- [ ] Commit: `perf(nginx): compress textual responses safely`.
|
|
|
|
## Task 3: Lazy-load landing case-study images
|
|
|
|
**Files:**
|
|
- Modify: `frontend/src/components/landing/sections/case-study-section.tsx`
|
|
- Create: `frontend/tests/unit/components/landing/case-study-section.dom.test.tsx`
|
|
|
|
- [ ] Write a DOM test that renders the section and asserts each card has an actual `img` with `loading="lazy"`, `decoding="async"`, intrinsic dimensions, descriptive alt text, and no inline/background-image URL.
|
|
- [ ] Run the focused test and capture RED against the CSS backgrounds.
|
|
- [ ] Replace background-image cards with a positioned `next/image` or native image. Keep the overlay and visual crop, set explicit `sizes`, and make only an above-the-fold image eager if measurement proves it is visible on initial viewport.
|
|
- [ ] Run the DOM test GREEN and verify in a browser/network trace that offscreen JPEG requests do not start before scrolling.
|
|
- [ ] Revert the component change, prove RED, restore, rerun GREEN.
|
|
- [ ] Commit: `perf(frontend): lazy load case study media`.
|
|
|
|
## Task 4: Replace request-derived mock filesystem traversal with a static manifest
|
|
|
|
**Files:**
|
|
- Modify: `frontend/src/core/threads/static-demo.ts`
|
|
- Modify: `frontend/src/app/mock/api/threads/[thread_id]/artifacts/[[...artifact_path]]/route.ts`
|
|
- Modify: `frontend/src/app/mock/api/threads/[thread_id]/history/route.ts`
|
|
- Modify: `frontend/src/app/mock/api/threads/search/route.ts`
|
|
- Modify: `frontend/src/app/workspace/page.tsx`
|
|
- Create: `frontend/tests/unit/core/threads/static-demo.test.ts`
|
|
- Create: `frontend/tests/unit/app/mock/static-artifact-route.test.ts`
|
|
|
|
- [ ] Add failing tests for `resolveStaticDemoArtifact(threadId, segments)` covering a known artifact, unknown thread, traversal segments, and encoded traversal. Add a route test that asserts the response comes from the manifest-backed resolver.
|
|
- [ ] Run both focused tests and capture RED.
|
|
- [ ] Define an explicit immutable demo manifest in `static-demo.ts`; normalize and validate all path segments before a lookup. Route handlers may read only paths returned by that manifest.
|
|
- [ ] Replace request-time `readdirSync`, `readFileSync`, and `statSync` in mock routes/workspace discovery with manifest imports or `fs/promises` during server execution. Keep response payloads byte-for-byte compatible.
|
|
- [ ] Run focused tests GREEN.
|
|
- [ ] Run `NEXT_PUBLIC_STATIC_WEBSITE_ONLY=true pnpm build` and assert the prior Turbopack "whole project unintentionally traced" warning and mock artifact import trace are absent.
|
|
- [ ] Revert the resolver use, prove the route test RED, restore, rerun focused tests and build.
|
|
- [ ] Commit: `perf(frontend): bound static demo file tracing`.
|
|
|
|
## Final verification
|
|
|
|
- [ ] Run `cd frontend && pnpm check && pnpm test`.
|
|
- [ ] Run `cd backend && uv run pytest tests/test_nginx_compression.py -q`.
|
|
- [ ] Run the static-demo production build and confirm zero unexpected-file/whole-project trace warnings.
|
|
- [ ] Record the new route measurements in the PR description; do not loosen a budget to make the gate pass.
|