Skip to content

Theme: Move build and Stylelint plugins to @wordpress/theme-build-tools - #83568

Merged
simison merged 14 commits into
trunkfrom
simison/theme-build-tooling-package
Oct 22, 2026
Merged

simison merged 14 commits into
trunkfrom
simison/theme-build-tooling-package

Conversation

@simison

@simison simison commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Depends on #76604

Previously:

What?

Moves the design token build plugins (PostCSS, Lightning CSS, esbuild, Vite) and the Stylelint rules from @wordpress/theme to a new package, @wordpress/theme-build-tools. The subpaths after the package name stay the same.

The old @wordpress/theme/*-plugins/* exports are removed, so consumers have to migrate when updating.

Update @wordpress/build, @wordpress/stylelint-config, Storybook and repo tooling to load the plugins from the new package.

Why?

The build tools only run at build time, so their peers don't belong on a runtime package. After this change, @wordpress/theme only has React peers.

1. Avoid consumer bundles ballooning due to duplicate versions of @wordpress/theme or @wordpress/ui due to mismatched @types/node versions.

Package manager pnpm creates a separate package instance for each distinct set of resolved peers, including transitive ones such as vite → @types/node. In a workspace where two @types/node versions coexist, @wordpress/theme, and @wordpress/ui through it, resolve twice, so bundles ship duplicate copies. dedupePeerDependents can't merge them, because the peer sets really differ.

This happens with pnpm (and anything else that copies packages per peer set). npm's hoisted node_modules doesn't split packages this way.

With the old peers: when a bundle's dependencies reach @wordpress/theme through different vite copies, the bundle gets two copies of theme. It also gets two copies of @wordpress/ui, because ui depends on theme. Each copy lives in its own folder, and the bundler includes both.
Without them: @types/node skew only splits vite. That's a build tool that never goes into a bundle, so nothing extra ships to the browser.

2. Make maintaining build tool peer dependencies å separate concern from runtime package

Suggested in #80952 (comment), although the tooling split to theme and ui didn't end up happening:

I wonder if we should have a separate package(s) for design system lint plugins. I already flagged the maintenance burden pain-point of keeping peer dependencies up to date for @wordpress/theme in #80267 (comment), and this creates another touch-point for us to manage over time.

The fact that these are peer dependencies in the first place creates an undesirable shared dependency, where someone who wants to use @wordpress/ui in their project that uses Stylelint now has to be concerned about whether @wordpress/ui keeps its own Stylelint peer dependencies up to date and potentially do a costly upgrade just so that they can continue using Stylelint. Even though they're "optional" peer dependencies, if a downstream project uses both @wordpress/ui and incidentally also uses stylelint, their version of stylelint will be validated against the version range we specify in our peer dependencies.

How?

  • Add packages/theme-build-tools
  • The plugins read token data through @wordpress/theme's public exports. This adds one new export: @wordpress/theme/design-token-fallbacks.js (code). The new public export also makes it easier for consumers to create their own plugins. Did not export design-tokens file (code).

Testing Instructions

  1. Run npm install && npm run build.
  2. Run npm run test:unit:vitest -- packages/theme-build-tools packages/theme packages/wp-build packages/stylelint-config.
  3. Run npm run typecheck && npm run lint:css.
  4. In Storybook, check that token fallbacks are still injected, for example var(--wpds-color-foreground-content-neutral, #1e1e1e).
  5. Run npm pack --dry-run in packages/theme and check that no *-plugins directories are included.

CI: lint:published-deps fails until @wordpress/theme-build-tools is published, because @wordpress/build's peer range has to be fetched from npm.

Use of AI Tools

claude

@simison
simison requested review from a team and youknowriad September 28, 2026 08:12
@simison simison added the [Type] Breaking Change For PRs that introduce a change that will break existing functionality label Sep 28, 2026
@simison simison added the [Package] Theme /packages/theme label Sep 28, 2026
@simison simison added the [Package] UI /packages/ui label Sep 28, 2026
@github-actions github-actions Bot added [Tool] ESLint plugin /packages/eslint-plugin [Tool] stylelint config /packages/stylelint-config [Package] wp-build /packages/wp-build and removed [Package] UI /packages/ui labels Sep 28, 2026
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

🎉 Props

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: simison <simison@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

📦 Bundle size

Size Change: 0 B

Total Size: 9.05 MB

eebfc2c Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 6cf084a trunk % Change
timeToFirstByte 55.95 ms +4.74% -5.36% 53.95 ms +4.08% -3.43% 3.71%
largestContentfulPaint 94 ms +6.38% -4.26% 88 ms +9.09% -0% 6.82%
lcpMinusTtfb 37.9 ms +10.69% -8.97% 34.45 ms +8.71% -3.63% 10.01%
wpBeforeTemplate 29.24 ms +9.64% -3.28% 28.45 ms +3.62% -1.97% 2.78%
wpTemplate 21.44 ms +3.87% -3.22% 21.56 ms +3.15% -6.4% -0.56%
wpTotal 51.8 ms +5.46% -4.88% 50.08 ms +4.69% -3.39% 3.43%
wpMemoryUsage 7.66 MB +0% -0% 7.63 MB +0% -0% 0.44%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric 6cf084a trunk % Change
timeToFirstByte 45.75 ms +6.34% -3.28% 45.7 ms +10.28% -2.08% 0.11%
largestContentfulPaint 100 ms +2% -4% 96 ms +8.33% -0% 4.17%
lcpMinusTtfb 52.3 ms +2.58% -1.05% 51.3 ms +4.48% -0.88% 1.95%
wpBeforeTemplate 26.3 ms +9.81% -2.4% 26.37 ms +11.07% -2.88% -0.27%
wpTemplate 16.12 ms +3.91% -3.66% 16.35 ms +6.18% -3.18% -1.41%
wpTotal 42.61 ms +6.71% -2.68% 42.72 ms +10.16% -1.78% -0.26%
wpMemoryUsage 6.35 MB +0% -0% 6.32 MB +0% -0% 0.54%
wpDbQueries 13 +0% -0% 13 +0% -0% 0%

media-processing

Metric 6cf084a trunk % Change
mediaProcessingJpeg 404.1 ms +1.13% -1.36% 405.89 ms +0.31% -0.05% -0.44%
mediaProcessingAvif 6136.38 ms +0.37% -0.17% 6181.51 ms +0.24% -0.24% -0.73%
mediaProcessingJpegToAvif 4246.91 ms +0.29% -0.11% 4254.2 ms +0.33% -0.12% -0.17%

media-upload

Metric 6cf084a trunk % Change
jpegUploadProcessing 1969.3 ms +1.22% -2.18% 1927.4 ms +0.79% -0.13% 2.17%
pngUploadProcessing 185.33 ms +36.58% -10.24% 219.22 ms +25.02% -21.83% -15.46%
largeJpegUploadProcessing 1922.43 ms +0.33% -0.34% 1938.68 ms +0.18% -0.6% -0.84%
multipleImageUploadProcessing 2027.9 ms +0.2% -0.86% 2035.55 ms +1.08% -0.64% -0.38%

post-editor

Metric 6cf084a trunk % Change
serverResponse 257.08 ms +5.98% -8.65% 268.01 ms +8.15% -5.3% -4.08%
firstPaint 328.56 ms +3.83% -3.9% 239.62 ms +37.39% -30.43% 37.12%
domContentLoaded 720.44 ms +2.07% -0.94% 720.37 ms +2.53% -2.91% 0.01%
loaded 721.34 ms +2.04% -0.92% 721.29 ms +2.54% -2.92% 0.01%
firstContentfulPaint 331.21 ms +3% -2.62% 330.25 ms +3.8% -8.31% 0.29%
firstBlock 2122.56 ms +1.39% -1.36% 2125.15 ms +2.35% -1.31% -0.12%
type 14.99 ms +1.13% -8.47% 13.13 ms +1.9% -3.66% 14.17%
typeWithoutInspector 13.28 ms +9.49% -4.44% 13.78 ms +20.68% -3.19% -3.63%
typeWithTopToolbar 16.93 ms +3.07% -2.36% 16.5 ms +5.27% -3.09% 2.61%
typeContainer 6.53 ms +1.84% -2.91% 6.38 ms +4.08% -8.46% 2.35%
focus 75.56 ms +6.75% -1.03% 70.92 ms +1.75% -1.23% 6.54%
firstFocus 149.25 ms +0% -0% 149.88 ms +0% -0% -0.42%
selectAll 375.96 ms +2.09% -1.07% 373.49 ms +0.34% -3.21% 0.66%
listViewOpen 51.94 ms +6.35% -9.7% 45.6 ms +4.43% -10.42% 13.9%
inserterOpen 27.72 ms +5.09% -9.49% 26.15 ms +8.49% -2.83% 6%
inserterHover 9.33 ms +6.86% -4.39% 8.5 ms +8.24% -2.35% 9.76%
inserterSearch 6.72 ms +1.79% -4.02% 6.58 ms +5.17% -2.58% 2.13%
loadPatterns 432.3 ms +8.42% -3.26% 452.15 ms +8.88% -6.68% -4.39%
wpTotal 250.32 ms +6.12% -8.91% 261.29 ms +8.32% -5.46% -4.2%
wpMemoryUsage 14.70 MB +0% -0% 14.66 MB +0% -0% 0.24%
wpDbQueries 55 +0% -0% 55 +0% -0% 0%

site-editor

Metric 6cf084a trunk % Change
serverResponse 515.06 ms +2.42% -4.28% 541.36 ms +2% -4.95% -4.86%
firstPaint 273.84 ms +26.9% -12.64% 300.26 ms +3.9% -6.7% -8.8%
domContentLoaded 1278.6 ms +1.4% -1.36% 1290.68 ms +2.81% -0.38% -0.94%
loaded 1279.9 ms +1.38% -1.35% 1291.92 ms +2.84% -0.37% -0.93%
firstContentfulPaint 517.53 ms +0.87% -3.07% 526.22 ms +3.66% -0.84% -1.65%
firstBlock 4859.24 ms +1.45% -0.98% 4917.63 ms +1.16% -1.66% -1.19%
type 19.7 ms +3.2% -4.82% 19.61 ms +8.11% -10.3% 0.46%
navigate 135.73 ms +7.32% -4.2% 128.34 ms +6.02% -6.3% 5.76%
loadPatterns 1318.07 ms +4.09% -2.99% 1240.38 ms +5.21% -8.94% 6.26%
loadPages 1019.68 ms +1.55% -3.86% 1032.05 ms +1.63% -2.17% -1.2%
wpTotal 505.1 ms +2.42% -4.38% 531.31 ms +2% -4.94% -4.93%
wpMemoryUsage 12.71 MB +0% -0% 12.68 MB +0% -0% 0.27%
wpDbQueries 44 +2.27% -0% 44 +2.27% -0% 0%

eebfc2c Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35
inserts a block in proper place after having clicked `Browse All` from inline inserter in /test/e2e/specs/editor/various/inserting-blocks.spec.js, passed after 1 failed attempt.
Error: apiRequestContext.fetch: socket hang up
Call log:
  - → GET http://localhost:8889/wp-json/wp/v2/blocks?per_page=100&status=publish%2Cfuture%2Cdraft%2Cpending%2Cprivate%2Ctrash
    - user-agent: Playwright/1.63.0 (x64; ubuntu 24.04) node/24.20 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - X-WP-Nonce: 368b9c7589
    - cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_23778236db82f19306f247e20a353a99=admin%7C1792843153%7Cco1gq5e2b5PqNovKg8P6qL87Vljuu8LPMI2QEFAp5eh%7C655387061561b72e5d6b23cc0fe756c05518bdb31d742b423b9490712ee0ac11; wp-settings-time-1=1792670354

    at RequestUtils.rest (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/rest.ts:112:39)
    at RequestUtils.deleteAllBlocks (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/blocks.ts:23:28)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/inserting-blocks.spec.js:11:22
refuses the drop and uploads nothing in /test/e2e/specs/editor/various/single-file-placeholder-drop.spec.js, passed after 1 failed attempt.
Error: expect(received).toHaveLength(expected)

Expected length: 0
Received length: 1
Received array:  [{"_links": {"about": [{"href": "http://localhost:8889/wp-json/wp/v2/types/attachment"}], "author": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/users/1"}], "collection": [{"href": "http://localhost:8889/wp-json/wp/v2/media"}], "curies": [{"href": "https://api.w.org/{rel}", "name": "wp", "templated": true}], "replies": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/comments?post=223"}], "self": [{"href": "http://localhost:8889/wp-json/wp/v2/media/223", "targetHints": {"allow": ["GET", "POST", "PUT", "PATCH", "DELETE"]}}], "wp:attached-to": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/posts/222", "id": 222, "post_type": "post"}]}, "alt_text": "", "author": 1, "caption": {"rendered": ""}, "class_list": ["post-223", "attachment", "type-attachment", "status-inherit", "hentry", "entry"], "comment_status": "open", "date": "2026-10-22T12:05:42", "date_gmt": "2026-10-22T12:05:42", "description": {"rendered": "<p class=\"attachment\"><a href='http://localhost:8889/wp-content/uploads/2026/10/b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png'><img loading=\"lazy\" decoding=\"async\" width=\"10\" height=\"10\" src=\"http://localhost:8889/wp-content/uploads/2026/10/b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png\" class=\"attachment-medium size-medium\" alt=\"\" style=\"width:100%;height:100%;max-width:10px;\" /></a></p>
"}, "featured_media": 0, "filename": "b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png", "filesize": 80, "guid": {"rendered": "http://localhost:8889/wp-content/uploads/2026/10/b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png"}, "id": 223, "link": "http://localhost:8889/?attachment_id=223", "media_details": {"file": "2026/10/b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png", "filesize": 80, "height": 10, "image_meta": {"alt": "", "aperture": "0", "camera": "", "caption": "", "copyright": "", "created_timestamp": "0", "credit": "", "focal_length": "0", "iso": "0", "keywords": [], "orientation": "0", "shutter_speed": "0", "title": ""}, "sizes": {}, "width": 10}, "media_type": "image", "meta": [], "mime_type": "image/png", "modified": "2026-10-22T12:05:42", "modified_gmt": "2026-10-22T12:05:42", "ping_status": "closed", "post": 222, "slug": "b56eeb0f-0e4f-4dd2-aa4a-73960130c14e", "source_url": "http://localhost:8889/wp-content/uploads/2026/10/b56eeb0f-0e4f-4dd2-aa4a-73960130c14e.png", "status": "inherit", "template": "", "title": {"rendered": "b56eeb0f-0e4f-4dd2-aa4a-73960130c14e"}, "type": "attachment"}]
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/single-file-placeholder-drop.spec.js:71:45

eebfc2c Run

simison added a commit that referenced this pull request Sep 28, 2026
Comment thread packages/wp-build/lib/build.mjs Outdated
try {
const { default: esbuildPlugin } =
await import( '@wordpress/theme/esbuild-plugins/esbuild-ds-token-fallbacks' );
await import( '@wordpress/theme-build-tools/esbuild-plugins/esbuild-ds-token-fallbacks' );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I know it's a precedent to this PR but are we concerned about wp-build having package specific build tooling?

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.

Here we don't have specific tooling for building the theme package, but we make wp-build apply a certain build step on everything it builds. Namely transforming all var(--wpds-foo) CSS variable references so that they contain a fallback.

That's a fairly normal build step that uses an external tool. Like the Emotion plugin, various CSS minifiers and postprocessors. And it's WP specific, like many other things: externalizing specific @wordpress/* packages, working with the routing framework, reading specific package.json fields...

These are reasons why I wouldn't be concerned much.

Comment thread packages/theme/CHANGELOG.md Outdated
Comment thread packages/wp-build/package.json Outdated
simison added a commit that referenced this pull request Sep 28, 2026
@simison
simison force-pushed the simison/theme-build-tooling-package branch from c6e175c to 95a7547 Compare September 28, 2026 13:56
Comment thread packages/wp-build/package.json Outdated
},
"peerDependencies": {
"@wordpress/theme": ">=0.8.0 <3.0.0"
"@wordpress/theme-build-tools": "^1.0.0-prerelease"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CI checks are failing because this package (and version) are not publicized yet on npm, maybe we could stage the new package's publication (or make the audit validate the local candidate before relying on this peer) ?

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 audit already supports validating the local candidate when the dependency is declared as file:.... But for peerDependencies the file:... specifier is not valid, there needs to be a version range. But a real version range implies a NPM download which doesn't exist yet... a chicken-egg situation.

A good solution is to land theme-build-tools as a normal dependency first and only after publishing to switch it to peer.

And by the way, maybe the theme build shouldn't be optional/peer at all? The wp-build uses the fallback plugin directly. And the fallbacks should be applied for all users of wp-build, it shouldn't depend on whether the consumer semi-randomly installs theme-build-tools in the same project.

For theme the peer dependency made sense, but for theme-build-tools it probably doesn't, as there is no other user of the build tools in the repo.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That direct-dependency organisation sounds like a good benefit coming out of this.

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.

It's the same chicken-and-egg situation with npm OIDC where you can set up OIDC for a package that is already published to npm, which means you can't set up OIDC for a fresh package until you publish it.

So, the hack here is to manually publish the first bare-minimum version and then let the tools do the job.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A good solution is to land theme-build-tools as a normal dependency first and only after publishing to switch it to peer.

Implemented in 0e35967, and I think it solves the CI issue, although it now enforces the theme version shipped with this package instead of one defined by the consumer. That seems fine. I can follow up to relax it again after package releases in a couple of weeks.

And by the way, maybe the theme build shouldn't be optional/peer at all? The wp-build uses the fallback plugin directly. And the fallbacks should be applied for all users of wp-build, it shouldn't depend on whether the consumer semi-randomly installs theme-build-tools in the same project.

There's cons/pros; optional/peer allows flexible Theme package versioning (and thus different WPDS tokens), but I think we should just take a stance that the linter and theme package should be updated together (i.e. they should match).

Comment thread packages/theme/package.json Outdated
"@babel/types": "^7.29.7",
"@jridgewell/remapping": "^2.3.5",
"@jridgewell/trace-mapping": "^0.3.31",
"@wordpress/theme": "file:../theme",

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.

This is the part I'm concerned about. The theme plugins are specifically coupled to the token data of any given theme package version. In the old setup, we could guarantee that the plugins match the theme package version that the consumer has installed. With this separate package, the theme version is now decoupled and kind of opaque. (I checked that before publishing Lerna replaces the file: expression with a normal registry version range, e.g. ^3.0.0.)

I'm afraid this may cause version mismatch confusion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, this is the main concern for me too, we may risk introducing even more compat / version syncing troubles than the ones we're trying to solve 🤔

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.

There should be a clear separation between

  • the token and theme data themselves
  • a tool that uses and applies them

If we have that clear separation (I think we do), then there shouldn't be a big concern. It's just like with any other build tool. For example, we can have an older version of browserslist, and still have the latest fresh database with browser data from caniuse-lite.

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.

If I'm not mistaken, the new setup means that package managers can install a nested copy of wp-theme here, which could be different from the wp-theme version that the consumer thinks they are using. This is a problem because the consumer needs to be using wp-theme validation that matches their target WP version, not the "latest fresh" tokens.

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 new setup means that package managers can install a nested copy of wp-theme

Oh yes, this looks like a bug, related to the dependency-audit discussion in the other thread. wp-theme should be a peer dependency of wp-theme-build-tools, because wp-theme has other usages in a project. And wp-theme-build-tools can be a direct dependency (not peer) of wp-build because it's just the tooling code that wp-build uses directly. And wp-theme-build-tools is supposed to get its token data from the installed peer. And fail gracefully when the peer is not found.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's cool, so outcome is that @wordpress/build and @wordpress/theme-build-tools don't need to stay in sync with @wordpress/theme version installed; but once they bump @wordpress/theme version and there are changes to tokens, consumers gets to update their CSS files as the linter will pick the changes up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking at the latest commit and its message, it looks like the plan is to use a direct dependency temporarily, then restore the optional peer after publication.

Let's make sure we keep track of that follow-up, and plan to verify that validation uses the app's selected theme version when another version is installed elsewhere in the dependency tree.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Follow-up in #85388

simison added a commit that referenced this pull request Sep 30, 2026
@simison
simison force-pushed the simison/theme-build-tooling-package branch from 95a7547 to 0549390 Compare September 30, 2026 09:29
Comment thread packages/theme-build-tools/package.json Outdated
Comment thread packages/wp-build/package.json
simison added a commit that referenced this pull request Oct 1, 2026
@simison
simison force-pushed the simison/theme-build-tooling-package branch from ff753be to bacfda3 Compare October 1, 2026 08:17
Comment thread packages/theme-build-tools/lib/theme-tokens.mjs Outdated
Comment thread packages/theme/package.json Outdated
@ciampo
ciampo requested review from jsnajdr and mirka October 20, 2026 13:01
@simison

simison commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

@ciampo yep, I wrote this comment earlier but looks like I didn't post it. @jsnajdr and @manzoorwanijk particularly since you noted before in that convo, how does this look now regarding versioning?

@jsnajdr jsnajdr left a comment

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.

This looks good now 👍

The theme-tokens module could be a bit simplified, and the imports better explained, but these are non-blockers.

Comment thread packages/theme-build-tools/lib/theme-tokens.mjs Outdated
Comment thread packages/theme-build-tools/lib/theme-tokens.mjs Outdated
simison added a commit that referenced this pull request Oct 22, 2026
@simison
simison force-pushed the simison/theme-build-tooling-package branch from 0e35967 to f42e71c Compare October 22, 2026 08:12
simison added a commit that referenced this pull request Oct 22, 2026
@simison
simison force-pushed the simison/theme-build-tooling-package branch from f42e71c to bb5460d Compare October 22, 2026 11:11
@simison
simison enabled auto-merge (squash) October 22, 2026 11:52
Move the design token fallback build plugins (PostCSS, Lightning CSS,
esbuild, Vite) and the Stylelint plugins from @wordpress/theme to a new
@wordpress/theme-build-tools package, keeping the same subpath exports.
The old @wordpress/theme/*-plugins/* exports are removed.

Update @wordpress/build, @wordpress/stylelint-config, Storybook and repo
tooling to load the plugins from the new package.
Make @wordpress/theme an optional peer dependency of
@wordpress/theme-build-tools, so the plugins use the token data of the
theme version installed in the project, and do nothing when it is
missing. Make @wordpress/theme-build-tools a regular dependency of
@wordpress/build, which now imports the plugins directly.
The design-token-fallbacks.js export the plugins read first ships in the
next major release of @wordpress/theme. Drop the dependency audit ignore
rule that covered resolving the peer to 2.2.0.
…xport

Derive the token list and fallback map from the tokens named export of
@wordpress/theme/design-tokens.js, added in #76604, instead of a separate
design-token-fallbacks.js export. With an older @wordpress/theme, the
Stylelint rule uses the default token-name list and the fallback plugins
do nothing.

Also require Node.js >=22.13.0 and stop listing Markdown files in
`files`, matching the other packages.
Remove a @wordpress/build changelog entry the rebase duplicated under
the released 0.25.0 heading, refresh the lockfile, and name the renamed
tsconfig.prebuilt.json in the changelog workflow comment.
Carry over the bump from #84544, which updated it in @wordpress/theme
before the dependency moved to this package.
Top-level await in the token loader made Node reject require() of every
plugin with ERR_REQUIRE_ASYNC_MODULE, so a CommonJS config could not just
swap @wordpress/theme for @wordpress/theme-build-tools. Load the optional
@wordpress/theme token data synchronously with createRequire instead.

Test that the plugins load with require(), and hide @wordpress/theme from
both import and require() in the test without it.
Make @wordpress/theme a regular dependency for now, instead of an
optional peer. A peer range on a @wordpress/theme version that is not on
npm yet fails the published-dependency audit, while a file: dependency is
checked against the local package. It also means the first release
always injects fallbacks, without consumers installing @wordpress/theme.

Switch back to an optional peer once the @wordpress/theme release with
the tokens export is published.
The rebase over the 2026-10-20 release merged this branch's entries into
the newly released @wordpress/theme 3.0.0, @wordpress/build 0.26.0 and
@wordpress/stylelint-config 27.0.0 sections.
@wordpress/theme is now a dependency at this branch's version, which
always has the tokens export, so read the token names from it instead of
falling back to the default export of older versions.
Return undefined for any error when loading @wordpress/theme token data,
instead of only for a missing package or subpath, as suggested in review.
@simison
simison force-pushed the simison/theme-build-tooling-package branch from bb5460d to eebfc2c Compare October 22, 2026 11:52
@simison
simison merged commit 5e25c6a into trunk Oct 22, 2026
95 checks passed
@simison
simison deleted the simison/theme-build-tooling-package branch October 22, 2026 12:22
@github-actions github-actions Bot added this to the Gutenberg 24.4 milestone Oct 22, 2026
@simison

simison commented Oct 22, 2026 •

Copy link
Copy Markdown
Member Author

Follow-up to continue support different versions of the installed @wordpress/theme:

The ranges would need to be updated manually, which is why I'm also looking at linting peer ranges:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Theme /packages/theme [Package] wp-build /packages/wp-build [Tool] ESLint plugin /packages/eslint-plugin [Tool] stylelint config /packages/stylelint-config [Type] Breaking Change For PRs that introduce a change that will break existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants