Skip to content

build: drop sourcemaps from the localstudio bundle, strip them from deploys - #1624

Merged
dawsontoth merged 1 commit into
stagefrom
claude/build-assets-size-8d0205
Aug 14, 2026
Merged

build: drop sourcemaps from the localstudio bundle, strip them from deploys#1624
dawsontoth merged 1 commit into
stagefrom
claude/build-assets-size-8d0205

Conversation

@dawsontoth

Copy link
Copy Markdown
Contributor

Why

npm run build:local emitted 94 MB of assets. 76% of that — 71 MB — was sourcemaps, because each one embeds sourcesContent, the full original text of every module it covers. build.sourcemap was an unconditional true, so every build mode paid for maps whether or not anything read them.

This is size containment, not source protection — the repo is public.

before after
build:local → bundled into the Harper distribution 94 MB 23 MB
deployed web/, replicated to every node 95 MB 23 MB

What changed

build.sourcemap becomes sourcemapFor(mode), because the three kinds of build want three different things:

build sourcemap why
pnpm build:local (localstudio) false ships inside Harper; nothing reads the maps
pnpm build --mode dev|stage|prod 'hidden' uploaded to Datadog, then stripped before deploy
bare pnpm build true unchanged — a developer inspecting a prod build locally

localstudio gets no maps at all. This is the UI bundled into the Harper distribution: the harper repo drives the build from its own scripts (roughly VITE_STUDIO_VERSION="v$(jq -r '.version' ../package.json)" pnpm run build:local) and packages the resulting web/ as-is. Nothing on that path uploads maps to Datadog or reads them, so they only inflated the published Harper package. Configuring the omission here rather than post-processing in harper means harper's build scripts need no change.

Deploy modes get 'hidden', and the six deploy-*.yaml workflows now delete the maps after the Datadog upload and before mv web deploy/. Datadog keeps its own copy and is their only consumer, so replicating ~71 MB to every node bought nothing. 'hidden' rather than true is load-bearing: it omits the trailing //# sourceMappingURL= comment that would otherwise dangle onto a 404 once the files are gone.

Verification

  • build:local: 94M → 23M, 0 maps, no dangling sourceMappingURL. (The one grep hit in ts.worker is a sourceMappingURL=${r} template literal inside the bundled TypeScript compiler, not a build reference.)
  • --mode prod: 173 maps written for the upload, and confirmed no sourceMappingURL comment in the bundles. Simulating the strip step takes it 95M → 23M with all 191 js / 7 css / 2 html intact.
  • Datadog symbolication still works without the comment — the one real risk here, so it was dry-run explicitly: datadog-ci sourcemaps upload --dry-run handled 173/173 sourcemaps, pairing each .js.map to its bundle by filename.
  • Bare vite build still emits linked maps.
  • dprint, oxlint, tsc -b clean; 291 test files / 2255 tests pass.

No behavioral change to the app — the shipped JS/CSS is byte-identical, only the maps alongside it differ.

Notes for reviewers

  • Monaco was investigated as the other suspect and came out clean: it is already curated in src/lib/monaco/setup.ts (8 languages, not all ~90), editor.api stays lazy, and the eager critical path is 1.93 MB uncompressed across 25 files. The 13.7 MB of Monaco JS is dominated by ts.worker (6.6 MB — the TypeScript compiler) and is genuinely load-on-demand. No change made there.
  • AGENTS.md gains a Builds section recording the per-mode policy and how Studio ships inside Harper, so localstudio maps don't get switched back on — that would silently add ~71 MB to the Harper package with no consumer and no failing test to catch it.
  • The maps already on prod persist until the next deploy overwrites web/; this takes effect going forward rather than retroactively.

🤖 Generated with Claude Code

…eploys

Sourcemaps were 76% of the build output — 71 MB of the 94 MB that `build:local`
produced — because each one embeds `sourcesContent`, the full original text of
every module it covers. `build.sourcemap` was an unconditional `true`, so every
mode paid for them whether or not anything read them.

Replace it with `sourcemapFor(mode)`:

- `localstudio` → `false`. This is the UI bundled into the Harper distribution;
  the harper repo builds it via `build:local` and packages `web/` as-is, and
  nothing on that path uploads or reads maps. Omitting them here keeps the fix
  on this side of the repo boundary, so harper's build scripts need no change.
  94 MB → 23 MB.
- `dev`/`stage`/`prod` → `'hidden'`. The deploy workflows now delete the maps
  after the Datadog upload and before `mv web deploy/`, so ~71 MB is no longer
  replicated to every node for a consumer that keeps its own copy. `'hidden'`
  omits the `//# sourceMappingURL=` comment that would otherwise dangle onto a
  404 once the files are gone; `datadog-ci sourcemaps upload` pairs maps to
  bundles by filename and never needs it (verified by dry-run: 173/173 paired).
- bare `vite build` → `true`, unchanged, so a developer inspecting a production
  build locally still gets linked maps.

Deployed payload goes 95 MB → 23 MB with all bundles, css and html intact. This
is size containment, not source protection — the repo is public.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dawsontoth
dawsontoth requested a review from a team as a code owner August 14, 2026 14:58

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces dynamic sourcemap configuration based on the build mode in vite.config.ts and documents this design in AGENTS.md. Sourcemaps are disabled for localstudio to optimize bundle size, set to 'hidden' for deploy modes (dev, stage, prod) to facilitate Datadog uploads while avoiding dangling source map comments, and enabled for local production builds. I have no feedback to provide.

@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 55.32% 6678 / 12071
🔵 Statements 55.93% 7188 / 12850
🔵 Functions 47.52% 1653 / 3478
🔵 Branches 49.3% 4661 / 9453
File CoverageNo changed files found.
Generated in workflow #1716 for commit 866c488 by the Vitest Coverage Report Action

@dawsontoth
dawsontoth requested a review from cb1kenobi August 14, 2026 16:36
@dawsontoth
dawsontoth enabled auto-merge August 14, 2026 16:36

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!
🤖 Reviewed with Codex

Comment thread vite.config.ts
*/
function sourcemapFor(mode: string): boolean | 'hidden' {
if (mode === 'localstudio') { return false; }
if (DEPLOY_MODES.has(mode)) { return 'hidden'; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All stage builds now emit hidden sourcemaps, but both stage workflows first run a verification build whose output is never uploaded: merge-queue runs stop after that build, while push/restart runs immediately rebuild and replace it. That leaves roughly 71 MB of unused map generation per verification build, contrary to the stated consume-only policy. Could the verification build disable maps (for example through a config-only environment switch), or could the redundant first build be skipped when the release build will run? — KrAIs (GPT-5)

@dawsontoth
dawsontoth added this pull request to the merge queue Aug 14, 2026
Merged via the queue into stage with commit 5cb8c90 Aug 14, 2026
2 checks passed
@dawsontoth
dawsontoth deleted the claude/build-assets-size-8d0205 branch August 14, 2026 21:10
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.

2 participants