Skip to content

chore(toolbar): drop lowlight all-grammar re-export and posthog-typed typings from bundle graph - #72760

Closed
haacked wants to merge 1 commit into
masterfrom
posthog-code/toolbar-graph-trim-lowlight-posthog-typed
Closed

chore(toolbar): drop lowlight all-grammar re-export and posthog-typed typings from bundle graph#72760
haacked wants to merge 1 commit into
masterfrom
posthog-code/toolbar-graph-trim-lowlight-posthog-typed

Conversation

@haacked

@haacked haacked commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Problem

The toolbar module-boundary graph check (frontend/bin/check-toolbar-graph.mjs) budget has been raised five times in the last week by unrelated PRs (#71460, #71808, #72041, #69730, #72073, and #72459), because the toolbar's input graph sat within ~50 KB of the 14.5 MB budget. Analysis of the esbuild metafile showed two large avoidable contributors:

  • lowlight's package index re-exports all – every highlight.js grammar, 192 files and ~1.2 MB of source – even though our code only uses the common set (37 grammars).
  • lib/posthog-typed is ~200 KB of generated event-name typings wrapped around a tiny runtime, reachable from the toolbar via keyboard-shortcut hooks.

Neither ships extra bytes to customers (tree-shaking and lazy chunks handle output size), but both count fully against the input-graph budget, eating headroom that unrelated PRs then have to bump.

Changes

  • Toolbar build (frontend/toolbar-config.mjs): resolve lowlight to a pared-down module exposing only createLowlight and common, bypassing the package index's all re-export. Grammar files in the graph drop from 192 to 37.
  • Add src/toolbar/shims/posthogTyped.ts, a runtime-equivalent shim for lib/posthog-typed (capture/captureRaw delegating to the posthog-js singleton, everything else proxied), and register it in the toolbar's shim map.

Result: toolbar input graph goes from 13.78 MiB (978 files) to 12.45 MiB (822 files), restoring ~2 MB of headroom under the 14.5 MB budget. Crossing edges (5), eager output size, and CSP checks are unchanged.

How did you test this code?

  • node frontend/bin/build-toolbar.mjs then all three toolbar checks pass: graph (12.45 MiB, 5 baseline edges, no forbidden packages), size (eager 1.55 MB under 1.66 MB budget, unchanged), CSP eval.
  • pnpm --filter=@posthog/frontend typescript:check passes.
  • Added a parity test in shims.test.ts that fails if the generated lib/posthog-typed module grows runtime surface the shim lacks – the regression this catches is toolbar code calling a new generated method that silently resolves to undefined on customer pages. Also two test.each cases asserting capture/captureRaw delegate to posthog-js capture.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

Not needed – build-internal change, no user-facing behavior.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Investigated why #72459 needed a toolbar budget bump: the metric counts pre-tree-shake source bytes, so SDK bumps and shared-file churn trip it without shipping bytes. Ranked contributors from the esbuild metafile; lowlight's all re-export and the generated posthog-typed module were the two biggest avoidable ones. Considered also decoupling ~/types from the graph (17 value importers) but deferred it as a larger structural change. Invoked /writing-tests before adding the shim parity test. Note: #72583 rewrites the graph check to boundary-only; this PR doesn't touch the budget constant so they compose cleanly.


Created with PostHog Code

… typings from the bundle graph

Resolve 'lowlight' in the toolbar build to a pared module exposing only
createLowlight and common. The package index re-exports `all`, which pulls
all 192 highlight.js grammars (~1.2 MB of source) into the bundle graph
while only the 37 common grammars are used.

Shim lib/posthog-typed (~200 KB of generated event typings) with a
runtime-equivalent capture/captureRaw proxy. A parity test guards against
the generated module growing runtime surface the shim lacks.

Toolbar input graph: 13.78 MiB -> 12.45 MiB (978 -> 822 files). Boundary
edges, eager output size, and CSP checks are unchanged.

Generated-By: PostHog Code
Task-Id: 40b722de-ba04-412c-96f4-35888826b7e9
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 64.51 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.24 MiB · 22 files no change ███░░░░░░░ 28.8% of 4.29 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.19 MiB · 3,001 files no change █████████░ 88.5% of 9.25 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.3 KiB ../node_modules/.pnpm/posthog-js@1.405.2/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
235.8 KiB src/taxonomy/core-filter-definitions-by-group.json
224.4 KiB ../node_modules/.pnpm/posthog-js@1.405.2/node_modules/posthog-js/dist/module.js
167.1 KiB src/queries/validators.js
154.3 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
106.0 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
93.2 KiB ../packages/quill/packages/quill/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

Dist folder size — 🟢 -209.8 KiB (-0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1355.06 MiB · 🟢 -209.8 KiB (-0.0%)

Playwright — all passed

All tests passed.

View test results →

@haacked haacked added the reviewhog ($$$) Reviews pull requests before humans do label Jul 21, 2026
@posthog

posthog Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🦔 ReviewHog reviewed this pull request

Nothing worth raising this time, so here's a calming gif instead:

Someone relaxing in a sunny garden

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 211ae08 · box box-7f6a37902830 · ready in 842s (push → usable) · build log · rebuilds on every push, torn down on close

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "chore(toolbar): drop lowlight all-gramma..." | Re-trigger Greptile

@pauldambra

Copy link
Copy Markdown
Member

👋 i'm removing the input budget here #72583
i don't think we need to track a budget of stuff we're going to tree-shake away

2 similar comments
@pauldambra

Copy link
Copy Markdown
Member

👋 i'm removing the input budget here #72583
i don't think we need to track a budget of stuff we're going to tree-shake away

@pauldambra

Copy link
Copy Markdown
Member

👋 i'm removing the input budget here #72583
i don't think we need to track a budget of stuff we're going to tree-shake away

@pauldambra

Copy link
Copy Markdown
Member
CleanShot 2026-07-22 at 00 06 54@2x

my first time using a computer 🫠

@posthog

posthog Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

@rafaeelaudibert
rafaeelaudibert self-requested a review July 21, 2026 23:27
Comment on lines +89 to +93
// lowlight's package index re-exports `all` — every highlight.js grammar, ~1.2 MB of
// source — alongside the `common` set our code actually uses. The re-export alone pulls
// all 192 grammars into the bundle graph, so resolve 'lowlight' to a pared-down module
// instead. Its relative imports bypass the package's exports map (which hides lib/).
const lowlightDir = path.dirname(require.resolve('lowlight'))

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.

The best question here is: why is lowlight being pulled here at all? Can we simply load lowlight lazily wherever it's being loaded? This way it will not be added to the same bundle as the toolbar

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good news: lowlight is already lazy. The product tours code loads it through a dynamic import, so esbuild splits the whole tiptap/lowlight chain into its own chunk (~662 KB) that only downloads when someone actually saves or previews a tour step in the toolbar. It never ships on page load.

I also measured what this PR actually saves in shipped bytes: 90 bytes eager, 0 deferred. The entire 1.33 MB "win" was in the pre-tree-shake input metric, which is exactly what #72583 deletes. Tree shaking was already throwing all of this away.

So this PR trades a shim, a parity test, and a build hack for 90 bytes. Not worth it. Closing in favor of #72583.

@haacked haacked closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewhog ($$$) Reviews pull requests before humans do

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants