Found while implementing objectui#6515. Filed unassigned, recording only — not graded, no type. Observational: nothing is broken, and the number is not moving. It is filed because a widely-relied-on premise is measurably not true.
Measured on a forced clean console build (rm -rf apps/console/dist && turbo run build --filter=@object-ui/console --force) of origin/main @ 28ed9ce8f plus objectui#6515's fix. The finding is a property of main, not of that branch.
What was measured
packages/app-shell/src/console/AppContent.tsx declares eight route views with
lazy(() => import('../views/<View>.js')). Cross-referencing those names against the
eager set in apps/console/dist/eager-closure.json (files[] IS the eager set — 52 of 508
chunks):
declared lazy() | in the eager closure? |
|---|
DashboardView | yes |
PageView | yes |
RecordDetailView | yes |
RecordFormPage | yes |
ReportView | yes |
SearchResultsPage | yes |
ComponentNavView | no |
ObjectDataPage | no |
Six of eight. And the edge is a static one straight from the entry chunk — not a
second dynamic import that merely happens to resolve early:
$ grep -o 'from"./RecordFormPage-D5jJD1gx.js"' apps/console/dist/assets/index-BE-9TM9n.js
from"./RecordFormPage-D5jJD1gx.js"
assets/index-*.js is the entry chunk. So the browser fetches and parses those six chunks
before first render regardless of the route, and React.lazy + <Suspense> around them
buys nothing for the console.
Where the edge comes from
packages/app-shell/src/index.ts re-exports the views from the package barrel
(export { RecordFormPage, … }), and the console imports @object-ui/app-shell from
modules that are themselves eager (e.g. apps/console/src/components/InternalFormRoute.tsx).
A barrel export is a static edge, so the split chunk is statically reachable from the entry
even though the only routing reference to it is a lazy() import.
Why this is worth a card rather than a comment
The lazy split is load-bearing in prose across this area. objectui#6515's own body reasons
from "RecordFormPage is lazy()-loaded BY AppContent, so a static import from the view
back into AppContent would create a source edge out of the lazily-split chunk" — that
reasoning is still correct about the source graph the budget gate weighs, and #6515's
repair (a leaf module in providers/) is right either way. But the adjacent belief that
these chunks are off the first-paint path is false for six of them, and that belief is the
kind of thing a future performance decision gets made on.
Two things a reader might reasonably want and which this card does NOT claim:
Suggested shape, if graded
Measure what the six chunks cost on the first-paint path (they are inside the 3234 KB the
gate already weighs, so the number is available from eager-closure.json directly), then
decide whether the console's own imports should stop going through the barrel. A gate that
fails when a lazy()-declared view lands in the eager set would keep the two in agreement
afterwards.
Related
- objectui#6515 — the card this was found under; its repair is unaffected.
- objectui#5324 / objectui#5924 — the eager-closure budget and the report this reads.
- objectui#6319 — the Bundle Analysis staleness window; a different defect in the same gate's neighbourhood.
Generated by Claude Code
Found while implementing objectui#6515. Filed unassigned, recording only — not graded, no type. Observational: nothing is broken, and the number is not moving. It is filed because a widely-relied-on premise is measurably not true.
Measured on a forced clean console build (
rm -rf apps/console/dist && turbo run build --filter=@object-ui/console --force) oforigin/main@28ed9ce8fplus objectui#6515's fix. The finding is a property ofmain, not of that branch.What was measured
packages/app-shell/src/console/AppContent.tsxdeclares eight route views withlazy(() => import('../views/<View>.js')). Cross-referencing those names against theeager set in
apps/console/dist/eager-closure.json(files[]IS the eager set — 52 of 508chunks):
lazy()DashboardViewPageViewRecordDetailViewRecordFormPageReportViewSearchResultsPageComponentNavViewObjectDataPageSix of eight. And the edge is a static one straight from the entry chunk — not a
second dynamic import that merely happens to resolve early:
assets/index-*.jsis the entry chunk. So the browser fetches and parses those six chunksbefore first render regardless of the route, and
React.lazy+<Suspense>around thembuys nothing for the console.
Where the edge comes from
packages/app-shell/src/index.tsre-exports the views from the package barrel(
export { RecordFormPage, … }), and the console imports@object-ui/app-shellfrommodules that are themselves eager (e.g.
apps/console/src/components/InternalFormRoute.tsx).A barrel export is a static edge, so the split chunk is statically reachable from the entry
even though the only routing reference to it is a
lazy()import.Why this is worth a card rather than a comment
The lazy split is load-bearing in prose across this area. objectui#6515's own body reasons
from "
RecordFormPageislazy()-loaded BYAppContent, so a static import from the viewback into
AppContentwould create a source edge out of the lazily-split chunk" — thatreasoning is still correct about the source graph the budget gate weighs, and #6515's
repair (a leaf module in
providers/) is right either way. But the adjacent belief thatthese chunks are off the first-paint path is false for six of them, and that belief is the
kind of thing a future performance decision gets made on.
Two things a reader might reasonably want and which this card does NOT claim:
ceiling, PASS, and finding(app-shell):
RecordFormPagepublishes a hand-rolledcurrent_user(noid, noisPlatformAdmin) becausebuildExpressionUsercannot be imported from a lazy view #6515 moved it by +242 bytes.package's public API, and third-party embedders import views from it. Whether the console
should reach the views through the barrel at all (rather than by deep path, which would
let the split take effect) is the actual question.
Suggested shape, if graded
Measure what the six chunks cost on the first-paint path (they are inside the 3234 KB the
gate already weighs, so the number is available from
eager-closure.jsondirectly), thendecide whether the console's own imports should stop going through the barrel. A gate that
fails when a
lazy()-declared view lands in the eager set would keep the two in agreementafterwards.
Related
Generated by Claude Code