chore(toolbar): drop lowlight all-grammar re-export and posthog-typed typings from bundle graph - #72760
Conversation
… 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
🤖 CI report✅ Bundle size — no changeUncompressed size of every built 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 budgetHow 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
🟢 Largest files eagerly shipped from
|
| 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%)
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
|
Reviews (1): Last reviewed commit: "chore(toolbar): drop lowlight all-gramma..." | Re-trigger Greptile |
|
👋 i'm removing the input budget here #72583 |
2 similar comments
|
👋 i'm removing the input budget here #72583 |
|
👋 i'm removing the input budget here #72583 |
|
👋 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. |
| // 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')) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.


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-exportsall– every highlight.js grammar, 192 files and ~1.2 MB of source – even though our code only uses thecommonset (37 grammars).lib/posthog-typedis ~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
frontend/toolbar-config.mjs): resolvelowlightto a pared-down module exposing onlycreateLowlightandcommon, bypassing the package index'sallre-export. Grammar files in the graph drop from 192 to 37.src/toolbar/shims/posthogTyped.ts, a runtime-equivalent shim forlib/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.mjsthen 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:checkpasses.shims.test.tsthat fails if the generatedlib/posthog-typedmodule grows runtime surface the shim lacks – the regression this catches is toolbar code calling a new generated method that silently resolves toundefinedon customer pages. Also twotest.eachcases asserting capture/captureRaw delegate toposthog-jscapture.Automatic notifications
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
allre-export and the generated posthog-typed module were the two biggest avoidable ones. Considered also decoupling~/typesfrom 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