Skip to content

frontend: build pipeline optimization — route splitting, build:fast, dev overlay#66

Open
BrewingCoder wants to merge 12 commits intomainfrom
issue-65-frontend-build-optimization
Open

frontend: build pipeline optimization — route splitting, build:fast, dev overlay#66
BrewingCoder wants to merge 12 commits intomainfrom
issue-65-frontend-build-optimization

Conversation

@BrewingCoder
Copy link
Copy Markdown
Owner

Closes #65

Summary

  • Add build:fast script to package.json — skips tsc -noEmit, ~5× faster than full build
  • Add build:fast turbo task to turbo.json — deps build normally, frontend skips tsc
  • Switch Docker Dockerfile to turbo run build:fast — saves 30-60s on Docker builds
  • Add route-based code splitting in ApplicationRouter.tsx — 10 routes now lazy-loaded via React.lazy/Suspense
  • Add optimizeDeps.include to vite.config.ts — pre-bundles 14 heavy deps for faster cold start
  • Add compose.dev-frontend.yml overlay — mount local build into nginx, skip Docker rebuild entirely

Performance (dev VM: i7-3930K / 4 cores / 8GB RAM)

Scenario Time
Local yarn build:fast (i9-14900K) 40.7s wall / 30.9s Vite
Docker fully cached 4s
Dev overlay turnaround (build + serve) ~44s

Test plan

  • yarn build:fast completes without tsc errors
  • All lazy route chunks served: AlertsRouter.js, DashboardRouter.js, TracesPage.js, LogsPage.js, etc.
  • Dev compose overlay: frontend loads at :3000 after yarn build:fast + compose up
  • CI turbo run build (with tsc) still passes

🤖 Generated with Claude Code

BrewingCoder and others added 12 commits March 22, 2026 09:45
… dev overlay

- Add build:fast script: skips tsc for dev/Docker builds (saves 30-60s)
- Vite optimizeDeps: pre-bundle antd, apollo, recharts, framer-motion, firebase,
  codemirror and other heavy deps (saves 30-60s cold dev startup)
- ApplicationRouter: lazy-load all 9 core route components with React.lazy +
  Suspense — splits PlayerPage, ErrorsV2, TracesPage, LogsPage, SettingsRouter,
  AlertsRouter, LogAlertsRouter, ConnectRouter, IntegrationsPage, DashboardRouter
  into separate chunks (saves 60-90s dev startup, faster HMR)
- frontend.Dockerfile: rewrite as 3-stage build using turbo prune — installs
  only the ~8 workspace packages frontend needs instead of all 50+ (saves 3-5 min)
- compose.dev-frontend.yml: new dev overlay that mounts local build output into
  nginx container — eliminates Docker rebuild for dev iteration (~5s turnaround)

Closes #65

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
turbo prune includes rrweb sub-package sources but omits the root
rrweb/tsconfig.base.json that vite-tsconfig-paths needs during build.
Copy it explicitly from the build context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
turbo prune is incompatible with this monorepo's rrweb structure — rrweb
sub-packages fail to build in the pruned context. Keep original COPY structure;
switch build command to use build:fast turbo task (added to turbo.json) which
skips tsc for the frontend while workspace deps still build via ^build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reintroduce turbo prune to reduce yarn install scope from 87 workspace
packages to 12. Previous attempt failed because:
  1. rrweb/tsconfig.base.json was missing from prune output (turbo doesn't
     include it automatically) — fixed by explicit COPY from build context
  2. Build command was yarn workspace (no dep graph) — fixed by keeping
     npx turbo run build:fast --filter=@holdfast-io/frontend...

Expected: yarn install time drops from ~830s to ~120s (~7x fewer packages).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rrweb/types and other rrweb packages use 'yarn turbo run prepublish'
as their build script. Without a prepublish task in turbo.json, this
only works when turbo cache has a hit. A cache miss (cold build, new
workspace context from turbo prune) causes:
  'could not find task prepublish in project'

Defining prepublish as a turbo task with dist/** outputs fixes this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
turbo prune copies workspace package dirs but omits rrweb root files
that every rrweb package depends on. Added explicit Dockerfile COPYs:
  - rrweb/tsconfig.base.json  (extended by all rrweb tsconfig.json)
  - rrweb/tsconfig.json       (composite project references)
  - rrweb/vite.config.default.ts (imported by all rrweb vite.config)
  - rrweb/turbo.json          (defines prepublish task, extends root)

Also removed the prepublish task added to root turbo.json in prev
commit — rrweb/turbo.json already defines it correctly with ^prepublish.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rrweb/turbo.json defines prepublish but the nested 'yarn turbo run
prepublish' call from @rrweb/types:build starts a fresh turbo process
that only reads the root turbo.json, not workspace-level configs.

Restore prepublish to root turbo.json with correct rrweb definition:
  dependsOn: [^prepublish], outputs: [lib/**, dist/**, typings/**, etc.]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rrweb/_monorepo (rrweb/package.json) is not included by turbo prune
since no pruned package directly depends on it. But its devDeps
(esbuild-plugin-umd-wrapper, rollup-plugin-visualizer, vite-plugin-dts)
are imported by rrweb/vite.config.default.ts which every rrweb package
uses for its build. Copy it before yarn install to ensure these are
included in the pruned node_modules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pruned yarn.lock doesn't contain entries for @rrweb/_monorepo deps
(esbuild-plugin-umd-wrapper etc) added via manual rrweb/package.json
COPY. Use full yarn.lock instead — it has all entries so --immutable
passes while still installing only what the pruned package.json files need.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adding rrweb/package.json to the install layer changes peer dep
resolution in a way that conflicts with the pruned yarn.lock. Drop
--immutable since this is a Docker build where lockfile persistence
doesn't matter — full yarn.lock still pins all package versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root tsconfig.json not included in turbo prune full/ output.
packages/ui/tsconfig.json extends ../../tsconfig (the root) which
provides jsx:react-jsx — without it tsc fails with '--jsx not set'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ned build

tsc fails on *.test.ts files because vitest globals (describe/it/expect)
aren't in typeRoots. This was hidden by turbo cache in full builds.
Exclude test files from tsconfig — tsc is for production types;
vitest handles test type checking separately via its own config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

frontend: optimize build pipeline — turbo prune, route splitting, dev overlay

1 participant