Repository navigation
Commit cf601ff
perf(console): stop the eager stylesheet scanning test files (objectui#6379) (#9661)
Part of #6379.
Deliberately **not** `Fixes`. This closes one measurable face of that
card and leaves its actual question open: merging this must not close
it. What remains open is stated under "What this does not do".
## What this does
`apps/console/src/index.css` declares 27 `@source` path globs across
`packages/**` plus its own tree, and carried **no `@source not` line at
all** — while reaching further than any other source-declaring entry in
this repo. Tailwind v4 scans source TEXT, not an import graph, so every
test file under those globs was a source for the render-blocking
`index-*.css` the console serves: **2373** test files in the packages it
names, plus this app's own.
`packages/components/src/index.css` (objectui#8446, objectui#9569) and
`packages/runner/src/index.css` (objectui#8454) already carried the
exclusion. This entry was the gap — and it is the one whose output is
render-blocking.
Two repository-root-anchored `@source not` lines close it. That anchor
is the one base covering **both** trees this entry scans: the package
globs, and Tailwind's automatic detection root, which is the process CWD
— here `apps/console`, where the build runs.
## Evidence
**Class-set diff** — every disappearing class accounted for. 19 classes
leave the compiled sheet, and all 19 were traced to test files. The diff
is measured on a build that still scans every shipped file, so anything
a shipped file genuinely emits survives by construction:
- `prose-lg`, `prose-slate` — 10,302 unminified bytes between them; the
typography plugin emits a very large rule block per `prose-*` variant.
- `mt-[3.7331px]` — the self-hosted sentinel of components' own
`index-css-scan-excludes-tests.test.ts`: a token that exists **only** to
prove that package's exclusion works, which this app was shipping to
users.
- `row-1`, `row-42`, `tab-1`, `zoom-10`, `top-200`, `m-9`, `order-1`,
`bg-none`, `md:p-3`, `mt-[3.7331px]`, `bg-[color:var(--brand)]`,
`flex-grow`, `h-[125px]`, `w-[250px]`, `[group:1]`, `pl-44`, `m-1` —
each traced to a `*.test.*` or `__tests__/` file.
- Near-misses checked by hand, all substring artifacts of the grep
rather than real uses: `m-1` inside `before:bottom-1`;
`flex-grow`/`h-[125px]`/`w-[250px]` inside runner's own comment listing
the classes **it** excludes. `pl-44` is the instructive one — the
shipped `KanbanImpl.tsx` emits `sm:pl-44` (which survives), the bare
`pl-44` came from a test.
- Reverse direction is empty: no class is **added**.
**Positive control** — a negative-only result would also be produced by
a scan that found nothing. A marker class injected into a shipped file
(`packages/components/src/ui/button.tsx`) still compiles under the new
lines; the file was restored and its blob hash re-verified against
`HEAD`.
**Ablation** — deleting the two lines turns the new pin test red on both
sentinels (`6379.0731px`, own tree; `3.7331px`, another package's tree),
confirming it can fail. Restored, hash re-verified.
**Sizes** — built, minified `index-*.css`:
| | raw | gzipped |
|---|---|---|
| before | 365,214 | 47,482 |
| after | 357,216 | 46,527 |
| delta | -7,998 (-2.19%) | -955 (-2.00%) |
**First contentful paint** — production build, served locally with boot
endpoints mocked and gzip on, Playwright, cache disabled, fresh context
per run, **median of 7 runs** per cell:
| profile | before | after |
|---|---|---|
| localhost, no throttling | 64 ms | 76 ms |
| 20 Mbps / 80 ms RTT | 288 ms | 292 ms |
| Fast 4G (4 Mbps / 70 ms) | 688 ms | 688 ms |
**FCP does not move.** 955 gzipped bytes is under 2 ms of transfer at 4
Mbps, below this measurement's resolution. Reported as measured rather
than rounded into a win.
The card's attribution does reproduce: FCP lands ~22 ms after the last
stylesheet finishes at every profile (Fast 4G: last stylesheet 665.8 ms,
FCP 688 ms), so first paint really is gated on the render-blocking CSS.
**Negative control — a scan-surface change deliberately NOT made.** This
entry opens with a bare `@import 'tailwindcss'`, so automatic source
detection is ON, and the sibling packages carry `source(none)`. Adding
it here looks like the obvious next step. Measured: automatic detection
contributes **exactly one** class beyond the explicit globs (`w-100`, 54
bytes, sourced from a doc under `apps/console/docs/`). Excluding this
app's 170 KB `CHANGELOG.md` — the objectui#9569 hazard — changes the
compiled sheet by **zero bytes**. So `source(none)` buys nothing here
and risks dropping a class for no measured gain; it is not in this diff.
## What this does not do
It does not shorten first paint, and it is not the fix for #6379. That
card's three routes were carved up by triage: route 3 (shrink the sheet
if its scan surface is wider than the eager route needs) is the only one
needing no product ruling, and this is route 3, carried out and
measured. The measurement says route 3's ceiling is ~2% of the
render-blocking CSS.
The remaining ~690 ms on Fast 4G is the sheet the app genuinely needs.
Reaching it requires route 1 (make the app CSS non-blocking) or route 2
(inline a critical subset) — both of which change what an unstyled first
frame is allowed to look like, or need a rule for what counts as
critical. Those are product rulings and are **not** touched here. #6379
stays open for them.
The 27 package globs were **not** narrowed. "This plugin is not on the
eager route" is a fact about the JS closure; whether an eager component
renders its classes is a separate question, and dropping a glob would
silently unstyle a lazily-loaded plugin. No measurement here supports
it.
## Gates run
`build` · `type-check` · `lint` (0 errors; the new file adds 0 of the
212 pre-existing warnings) · full `@object-ui/console` suite (101 files,
1158 tests) · `check:control-bytes` · `check:new-line-citations` ·
`check:eager-closure` · `check:eager-locale-catalogues` ·
`check-changeset-presence` · `check-governed-queue-guard --test` (not a
governed surface).
The **performance-budget** workflow reaches this diff. Read in full: it
pins `MAX_ENTRY_GZIP_KB=350` against `index-*.js` only, selected by
`find ... -name 'index-*.js'`. It never measures CSS, so no pinned
number moves. `check:eager-closure` passes unchanged.
---
_Generated by [Claude
Code](https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent c42554e commit cf601ff
3 files changed
Lines changed: 199 additions & 0 deletions
File tree
- .changeset
- apps/console/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
58 | 90 | | |
59 | 91 | | |
60 | 92 | | |
| |||
0 commit comments