Skip to content

wp-build: Add --no-script-debug flag to skip debug assets#75396

Open
kraftbj wants to merge 7 commits intoWordPress:trunkfrom
kraftbj:fix/wp-build-script-debug-fallback
Open

wp-build: Add --no-script-debug flag to skip debug assets#75396
kraftbj wants to merge 7 commits intoWordPress:trunkfrom
kraftbj:fix/wp-build-script-debug-fallback

Conversation

@kraftbj
Copy link
Contributor

@kraftbj kraftbj commented Feb 10, 2026

What?

Closes #75395

Adds a --no-script-debug flag to wp-build that skips generating unminified
debug assets (.js / .css counterparts to .min.js / .min.css). Also
updates the PHP registration templates so SCRIPT_DEBUG falls back gracefully
when those files aren't present.

Why?

The unminified assets are useful for development with SCRIPT_DEBUG, but for
plugins shipping via WordPress.org they can significantly increase the
distribution size — often doubling the JavaScript footprint of the build/
directory. Plugin authors who don't expect their users to debug bundled scripts
may want to exclude them.

Without this change, excluding unminified files breaks SCRIPT_DEBUG — registered
script URLs point to non-existent files.

How?

Three pieces working together:

  1. CLI flag (--no-script-debug): When set, wp-build skips generating
    unminified JS, CSS, and script module assets. Without the flag, behavior is
    unchanged.

  2. Build-time constant (has_debug_assets): Emitted in constants.php so
    the PHP templates know at registration time whether unminified files exist —
    no runtime file_exists() needed.

  3. Template updates: In 4 PHP templates (script-registration,
    module-registration, routes-registration, style-registration), the
    SCRIPT_DEBUG extension logic checks has_debug_assets before choosing the
    unminified path:

    $extension = '.min.js';
    if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && $build_constants['has_debug_assets'] ) {
        $extension = '.js';
    }

    This also fixes bare SCRIPT_DEBUG usage (without defined() guard) in
    script-registration and style-registration — these would emit a warning
    on PHP 8+ when SCRIPT_DEBUG is not defined.

Testing Instructions

  1. Build a project with wp-build (no flag) — verify both .js and .min.js
    files are generated, and SCRIPT_DEBUG = true loads unminified files
  2. Build with wp-build --no-script-debug — verify only .min.js files are
    generated
  3. With the --no-script-debug build and SCRIPT_DEBUG = true, verify minified
    files are loaded (no 404s)
  4. With SCRIPT_DEBUG = false, verify minified files are always loaded (no change)

Testing Instructions for Keyboard

N/A — no UI changes.

Add file_exists checks to the PHP registration templates so that
SCRIPT_DEBUG gracefully falls back to .min.js/.min.css when unminified
files are not present on disk.

Also fix bare SCRIPT_DEBUG usage (without defined() guard) in
script-registration and style-registration templates.
@github-actions
Copy link

github-actions bot commented Feb 10, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

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: kraftbj <kraftbj@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: simison <simison@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: mcsf <mcsf@git.wordpress.org>

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

@github-actions github-actions bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Feb 10, 2026
@github-actions
Copy link

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @kraftbj! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@youknowriad
Copy link
Contributor

Thanks for the PR, at first sight, this feels like extra complexity, so I'm wondering why it's needed.

Why do we check for file existence knowing that wp-build is supposed to generate both all the time.

@kraftbj
Copy link
Contributor Author

kraftbj commented Feb 12, 2026

That's the overall issue—do we need to ship the unminified versions? We're using wp-build with the Jetpack Forms package's new editor which yielded 2.7 MB of unminified JS (compared to the 1.2 MB of minified JS).

Between Jetpack 15.4 and 15.5's final build artifacts, we saw the amount of JS shipped jump from 16k to 77k LOC. 51k of that was content.js files from the Forms wp-build generated unminified code.

The impact we see is that servers can choke upon upgrade especially with large plugin ZIPs. Jetpack is already huge and seeing how much was added via unminified code that is virtually never loaded, it seems like something we can optimize (in addition to any potential optimization in the code itself).

We're looking to work around this in Jetpack by excluding unminified versions in the production builds ( Automattic/jetpack#47044 ).

Another solution would be to let wp-build have a production mode that would delete the unminified code and not provide the SCRIPT_DEBUG option. I figure this approach would have a smaller impact on wp-build internals and allow for plugins who want to shave off some MBs.

@youknowriad
Copy link
Contributor

That's the overall issue—do we need to ship the unminified versions?

I believe we do personally, this is what allows developers to debug their code. SCRIPT_DEBUG exists in Core forever now. Both Core and Gutenberg ship both to production. I have a hard time understanding why this wouldn't be a good thing for folks using Jetpack as well.

@simison
Copy link
Member

simison commented Feb 12, 2026

That's the overall issue—do we need to ship the unminified versions? We're using wp-build with the Jetpack Forms package's new editor which yielded 2.7 MB of unminified JS (compared to the 1.2 MB of minified JS).

BTW the plan is to eventually use the same build script for all other 10+ dashboards and blocks as well.

On the flip side, it'll get rid of lots of boiletplate code in source files themselves.

When `--production` is passed, wp-build skips generating unminified
`.js` and `.css` files, reducing output size for distribution builds.

A `has_debug_assets` constant is written to `constants.php` so the
PHP registration templates can choose the correct file extension at
runtime without `file_exists()` checks.
@kraftbj
Copy link
Contributor Author

kraftbj commented Feb 26, 2026

Updated the approach based on the feedback here. Instead of runtime file_exists() fallbacks, this now adds a --production flag to wp-build that:

  1. Skips generating unminified .js and .css files entirely
  2. Writes a has_debug_assets constant into constants.php so the PHP registration templates know at build time whether debug assets exist—no filesystem probing needed

Default behavior is unchanged—both minified and unminified files are generated, and SCRIPT_DEBUG works as expected. The --production flag is opt-in for plugins that want to reduce their distribution size.

For Jetpack, this means we can run wp-build --production in our release pipeline instead of post-hoc deleting files or maintaining exclude lists. The runtime behavior is clean: SCRIPT_DEBUG=true with a production build gracefully stays on .min.js because has_debug_assets is false.

@youknowriad
Copy link
Contributor

I still don't understand why Jetpack would do that though, this was my initial question. It feels like it goes against the logic of the SCRIPT_DEBUG flag offered in WordPress (and for WordPress plugins)

@kraftbj
Copy link
Contributor Author

kraftbj commented Feb 26, 2026

Happy to give more context on the Jetpack side.

Plugin distribution size has real consequences. Jetpack is a large plugin and we've had recurring issues where hosts or the WordPress.org SVN infrastructure struggle to process upgrades due to the overall ZIP size. The Forms dashboard was our first use of wp-build, and it added one of the largest single-feature code increases we've ever shipped—2.7 MB of unminified JS on top of 1.2 MB of minified JS. Between Jetpack 15.4 and 15.5, the shipped JS line count jumped from ~16k to ~77k LOC, with 51k of that being unminified content.js files from wp-build output.

Unminified files in a production ZIP have zero runtime benefit for the overwhelming majority of sites. SCRIPT_DEBUG is a developer tool—it's not something a typical Jetpack install on a shared host will ever use. So we're shipping ~2x the JS footprint to every site to support a development workflow that almost none of them use.

I also did some quick analysis on why the output is so large, and there may be a broader conversation worth having about wp-build's tree-shaking. The Forms build/ directory currently ships ~6.9 MB total: 3.3 MB of unminified JS, 1.5 MB minified, and 2.1 MB of source maps. A comparable webpack build of the same source produces 533 KB of minified JS—a 60% reduction—primarily because webpack eliminates ~800 KB of dead code that esbuild includes. Even just the minified output from wp-build is ~2.5x larger than the webpack equivalent.

This --production flag is a quick, low-risk win for plugins like Jetpack in the meantime. But there may be some larger conversations that could help address the same issue.

@youknowriad
Copy link
Contributor

youknowriad commented Feb 26, 2026

SCRIPT_DEBUG is a developer tool—it's not something a typical Jetpack install on a shared host will ever use. So we're shipping ~2x the JS footprint to every site to support a development workflow that almost none of them use.

Yes, but it's a runtime config, I feel like you're saying that you prefer if we remove it from Core and it's just a dev tool at the moment of development. Which is something you can decently argue for, you lose the ability to debug core scripts as a plugin or a parent plugin as an add-on or any plugin as a site owner but it's not totally unimaginable.

I also did some quick analysis on why the output is so large, and there may be a broader conversation worth having about wp-build's tree-shaking. The Forms build/ directory currently ships ~6.9 MB total: 3.3 MB of unminified JS, 1.5 MB minified, and 2.1 MB of source maps. A comparable webpack build of the same source produces 533 KB of minified JS—a 60% reduction—primarily because webpack eliminates ~800 KB of dead code that esbuild includes. Even just the minified output from wp-build is ~2.5x larger than the webpack equivalent.

I'm curious about this, when I iteratively migrated all of the Gutenberg packages from webpack to esbuild, I didn't see any meaningful difference like that. I think there might be something else at play here in your testing. For instance "wp-build" bundles CSS within the JS while webpack might be extracting it to separate files causing different results (if you're using import style.css in your JS files)...

This --production flag is a quick, low-risk win for plugins like Jetpack in the meantime. But there may be some larger conversations that could help address the same issue.

Yes, I don't mind the flag but I would not call it production, I'd call it --no-script-debug or something, to clarify the reality, because without the flag it's also "production".

I'd like to ask for other opinions as well cc @jsnajdr @mcsf @aduth @Mamaduka

@youknowriad
Copy link
Contributor

it added one of the largest single-feature code increases we've ever shipped—2.7 MB of unminified JS on top of 1.2 MB of minified JS. Between Jetpack 15.4 and 15.5, the shipped JS line count jumped from ~16k to ~77k LOC, with 51k of that being unminified content.js files from wp-build output.

I think it's important to clarify here that the size of the zip or the added files have no impact on the user, if there's any impact on the user, it's a good impact because they can know debug scripts if needed.

@Mamaduka
Copy link
Member

I'd call it --no-script-debug or something, to clarify the reality, because without the flag it's also "production".

A similar flag seems okay. I know lots of plugins don't ship script-debug-compatible builds, and probably most users don't care. Which kind of goes against the spirit of the open web, but I can understand the need for it.

Another concern I have is regarding the wp-build package, which is supposed to be an opinionated build system. If we start introducing more and more flags for edge cases, are we going to repeat mistakes from wp-script?

P.S. The plugin size also came up recently for Gutenberg - #75088.

@kraftbj
Copy link
Contributor Author

kraftbj commented Feb 27, 2026

I'll update the flag and double-check my debugging into the differences into webpack vs esbuild.

I think it's important to clarify here that the size of the zip or the added files have no impact on the user, if there's any impact on the user, it's a good impact because they can know debug scripts if needed.

The whole reason Jetpack tracks the overall size of the plugin is due to upgrade failures due to servers glitching during the unzip/upgrade process when trying to process large updates. WordPress, with the plugin upgrade sandbox, has made these failures far less likely to actually break the site as it used to, but failed updates still occur.

@kraftbj kraftbj changed the title wp-build: Fall back to minified assets when unminified files are absent wp-build: Add --no-script-debug flag to skip debug assets Feb 27, 2026
@mcsf
Copy link
Contributor

mcsf commented Feb 27, 2026

More than going against the spirit of the open Web, couldn't it be argued that distributing only minified sources violates copyleft licences? It seems to be a grey area, from what little I saw. And while more scrupulous vendors may sort of make up for it by guaranteeing the sources are easy to find somewhere else, I worry that opening the door for this choice, by introducing a switch in what could become an official build tool for WordPress (de jure or de facto, doesn't matter), would be a mistake.

@kraftbj
Copy link
Contributor Author

kraftbj commented Feb 27, 2026

The GPLv2 is clear that source code can be conveyed separately from the object code if it has an offer to send the source code via written request, valid for at least three years. Linking to GitHub fulfills that.

The GPLv3 is clear that having the source available on a networked server operated by a third-party if the distributed code clearly indicated where that location is at.

I understand the philosophical argument but it is not a GPL violation to distribute compiled code that directs consumers to the source code.

Edited to add: The w.org plugin guidelines also specifically allows it.

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

Labels

First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository [Package] wp-build /packages/wp-build [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wp-build: Add --no-script-debug flag to skip unminified asset generation

5 participants