Skip to content

perf(components): stop shipping design-token build metadata to the browser - #3007

Merged
mfal merged 2 commits into
mainfrom
claude/design-tokens-runtime-json
Aug 31, 2026
Merged

perf(components): stop shipping design-token build metadata to the browser#3007
mfal merged 2 commits into
mainfrom
claude/design-tokens-runtime-json

Conversation

@Lisa18289

Copy link
Copy Markdown
Member

useDesignTokens imported the design tokens' full style-dictionary output. Every one of the 1538 tokens carries filePath, isSource, original, name, attributes and key — 94 % of the file, turning 49 KB of values into 834 KB per theme. Both themes are imported statically and the hook hangs off the default entry, so no consumer can tree-shake it. CategoricalColors pulled the same file just to read Object.keys(tokens.color.categorical).

style-dictionary now emits a second, leaner build to dist/json-runtime/ — same nested shape, only value and path per token. The three imports in components point at it. No other code changes: every consumer reads .value, the docs' DesignTokenTable additionally .path.

before after
chunks in the bundle 1371 KB 330 KB
over the wire (gzip) 105 KB 33 KB

dist/json/ is unchanged. It stays a published export: original — the unresolved reference, on 1315 of 1538 tokens — exists nowhere else in machine-readable form. A no-restricted-imports rule keeps it out of every src/, which is where this went wrong in the first place.

Why this targets main and not a major line

useDesignTokens is not part of public.ts, and the semver contract lists TypeScript types and design-token values as explicitly best-effort. MIGRATION.md documents the removed fields for anyone who read them, and points at json/all-light.json as the build-time source.

Verification

  • All 1538 values byte-identical between the two builds — nothing renders differently.
  • test:compile, 206 unit tests, 250 browser tests (webkit), 354 visual tests (incl. CartesianChart and LoadingSpinner), affected:test across 7 projects, pnpm lint — green.
  • Clean build confirms the fat chunks are gone rather than merely unreferenced.
  • Docs Colors page renders unchanged (12 tables, 128 rows, swatches resolve).

🤖 Generated with Claude Code

…owser

`useDesignTokens` imported the design tokens' full style-dictionary output,
which carries `filePath`, `isSource`, `original`, `name`, `attributes` and
`key` on every one of the 1538 tokens. That metadata is 94 % of the file — it
turns 49 KB of values into 834 KB per theme.

Both themes are imported statically, and the hook hangs off the default entry,
so no consumer could tree-shake it: 1.37 MB of JavaScript in every bundle that
touches the package. `CategoricalColors` pulled the same file just to read
`Object.keys(tokens.color.categorical)`.

style-dictionary now emits a second, leaner build to `dist/json-runtime/`,
keeping only `value` and `path` per token in the same nested shape. The three
imports in `components` point at it; no other code changes, because every
consumer reads `.value` (the docs' `DesignTokenTable` additionally `.path`).

    chunks in the bundle   1371 KB -> 330 KB  (-76 %)
    over the wire (gzip)    105 KB ->  33 KB  (-69 %)

All 1538 values are byte-identical between the two builds, so nothing renders
differently.

`dist/json/` stays as it is — it is a published export, and `original` (the
unresolved reference, on 1315 of 1538 tokens) exists nowhere else in
machine-readable form. A `no-restricted-imports` rule keeps it out of every
`src/`, which is where this went wrong in the first place.

Not routed to the major line: `useDesignTokens` is not part of `public.ts`, and
the semver contract lists TypeScript types and design-token values as
best-effort (docs/release-workflow.md). MIGRATION.md documents the removed
fields for anyone who read them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Lisa18289 Lisa18289 self-assigned this Aug 31, 2026
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./packages/components/

Status Category Percentage Covered / Total
🔵 Lines 76% 627 / 825
🔵 Statements 75.91% 643 / 847
🔵 Functions 77.95% 145 / 186
🔵 Branches 66.66% 298 / 447
File CoverageNo changed files found.
Generated in workflow #6453 for commit 3bffa53 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

Preview environments are ready:

Type URL
docs pr-3007.docs.review.flow-components.de
storybook pr-3007.storybook.review.flow-components.de

Images:

  • docs: ghcr.io/mittwald/flow/docs:pr-3007
  • storybook: ghcr.io/mittwald/flow/storybook:pr-3007

…idance

Token counts and file sizes shift with every added token, and neither AGENTS.md
nor a lint message gets re-measured when they do. Both now state the ratio
qualitatively; the numbers stay in MIGRATION.md, where they describe one
specific version transition and cannot go stale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Lisa18289
Lisa18289 force-pushed the claude/design-tokens-runtime-json branch from a30e385 to 3bffa53 Compare August 31, 2026 11:03
@Lisa18289
Lisa18289 marked this pull request as ready for review August 31, 2026 11:06
@Lisa18289
Lisa18289 requested a review from a team August 31, 2026 11:06
@mfal
mfal merged commit 7d3afde into main Aug 31, 2026
22 checks passed
@mfal
mfal deleted the claude/design-tokens-runtime-json branch August 31, 2026 11:14
mfal added a commit that referenced this pull request Aug 31, 2026
Brings 1.0.16 (#3007) onto the promotion branch. Three resolutions worth
recording:

CHANGELOG.md — `merge=ours` (ADR 0004 §3) is written for main → next and drops
the incoming side, which here silently deleted main's own 1.0.16 entry. Every
changelog was rebuilt as main's file with our 1.1.0 entry spliced on top, so the
stable history publish.yml extracts release bodies from stays intact.

MIGRATION.md — the conflict is structural, not textual: main hand-maintains that
file, next generates it from the codemods catalogue, so any hand-merge would be
undone by the next build (and fail CI's generated-code check). Took the
generated side and carried main's note to its source as a catalogue entry
(use-design-tokens-build-metadata-removed), which also makes it reachable from
`flow-codemods list`/`upgrade`.

That entry's `since` is 1.0.16, not the `>=1.0.12` main's hand-written heading
claimed — #3007 merged with main at 1.0.15 and is publishing as 1.0.16.
guide.test.ts pins the newest entry's id as a canary and was updated to it;
remoteScope.test.ts requires a `targets` record per entry (asserted as exact set
equality), so it got one — `useDesignTokens` is not in the remote package's
export surface, hence `remotePackage: false`.
mfal added a commit that referenced this pull request Aug 31, 2026
A semantic merge conflict, not a textual one: #3007 (on main) added the
no-restricted-imports rule forbidding @mittwald/flow-design-tokens/json/* under
any src/, and next carries this importer from #2897. Neither side conflicted, so
the merge was clean and lint failed afterwards.

The consumer only reads `path` and `value` via collectTokensInPath, which is
exactly what json-runtime exposes — so this is the swap the rule's own message
prescribes, not a workaround.
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