Repository navigation
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Flips the fallback in `script_concat_settings()` so an undefined `CONCATENATE_SCRIPTS` resolves to `false` instead of `true`, making `load-scripts.php` and `load-styles.php` opt-in. Sites that want the previous behaviour can define the constant as `true`. The concatenation code paths are unchanged, and the surrounding guard already forces the global to `false` outside of `is_admin()` and `login_init`, so only wp-admin and the login screen are affected. See #57548.
haqadn
force-pushed
the
57548-disable-concatenation-by-default
branch
from
August 16, 2026 23:02
b5d66ea to
1e34129
Compare
Trunk moved the default for the `$concatenate_scripts` global out of `script_concat_settings()` and into `wp_should_concatenate_admin_scripts()`, which the login screen's prefetching also uses to predict whether the admin will concatenate. The conflict in `script_concat_settings()` is resolved to trunk's version, and this branch's change, making an undefined `CONCATENATE_SCRIPTS` mean `false` rather than `true`, is applied in `wp_should_concatenate_admin_scripts()` instead, along with the function's description and its filter's `@param`, which state the default. The prefetching therefore follows the new default too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fault Two tests still expected an undefined `CONCATENATE_SCRIPTS` to mean concatenation unless `SCRIPT_DEBUG` is on. They passed when run from `src/`, where `SCRIPT_DEBUG` is on and turns concatenation off whatever the default, but would fail where it is off. They now expect no concatenation unless the constant is defined as true. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TinyMCE was registered as the prebuilt `wp-tinymce.js` bundle only when scripts were both concatenated and compressed, and otherwise as TinyMCE core plus the compat3x plugin. Both conditions are on their way out: concatenation is now off by default, and `$compress_scripts` has not compressed anything since PHP compression was removed from the loaders in r43580 and from `wp-tinymce.php` in r44651. TinyMCE is now registered as the separate files regardless, which is how it is served on the front end and in the admin by default. The bundle holds the modern theme and all 22 plugins, which TinyMCE otherwise loads itself only when an editor is initialized. The block editor loads TinyMCE on every screen but only initializes it for a Classic block, so most screens skip about 300 KB. The `$force_uncompressed` parameter is now unused. The script_concat_settings() call stays, since this is where an admin screen settles the concatenation settings, as the `wp_should_concatenate_admin_scripts` filter documents. A site can still register the bundle under the `wp-tinymce` handle itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `$wp_scripts` global is typed as `mixed`, which PHPStan rejects as the `WP_Scripts` argument to wp_register_tinymce_scripts(). The wp_scripts() accessor returns a `WP_Scripts` instance, initializing the global first if needed. The `true` passed as the second argument is dropped too, since that parameter is no longer used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since TinyMCE is always registered as separate files, the `$force_uncompressed` parameter has nothing left to force. It is renamed to `$deprecated` and typed with `@phpstan-param false`, as for other deprecated parameters, so that PHPStan reports any caller still passing `true`. Passing a truthy value also triggers _deprecated_argument(), which uses the parameter and so resolves its `function.unusedParameter` error. _WP_Editors::force_uncompressed_tinymce() no longer passes `true`, so it does not trigger the notice. The signature also gains a `void` return type, which resolves the `missingType.return` error reported on the changed line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deprecation notice in wp_register_tinymce_scripts() was triggered only for a non-empty `$deprecated`, so a caller passing `null`, `0` or an empty string went unnoticed. Since `false` is the only value the parameter accepts, as its `@phpstan-param` says, any other value now triggers the notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Trac ticket: https://core.trac.wordpress.org/ticket/57548
Flips the fallback in
wp_should_concatenate_admin_scripts()so an undefinedCONCATENATE_SCRIPTSresolves tofalseinstead oftrue.load-scripts.phpandload-styles.phpbecome opt-in — sites that want the current behavior candefine( 'CONCATENATE_SCRIPTS', true ).Since r64120,
wp_should_concatenate_admin_scripts()holds the default thatscript_concat_settings()gives the$concatenate_scriptsglobal, and it is also what the login screen's prefetching uses to predict whether the admin will concatenate. Flipping the default there changes both at once, so they cannot disagree. (This PR originally flipped it inline inscript_concat_settings(); the merge with trunk after r64120 moved the change into the new function, along with the function's docs and its filter's@param, which state the default, and updated the tests of the default.)Scope is narrower than the constant's name suggests.
script_concat_settings()only applies this default on admin screens and the login screen, and leaves the globalfalseeverywhere else, so only wp-admin and the login screen change. The concatenation code paths themselves are untouched.Separately, TinyMCE is now always registered as separate files instead of the prebuilt
wp-tinymce.jsbundle, whether or not scripts are concatenated. See "Notes about TinyMCE" below.Two reasons to make this the default:
SCRIPT_DEBUGbeing ignored (#52879), translations not printing for concatenated handles (#50999), and"use strict"leaking between bundled scripts (#65515) are all conditions a stock install currently ships into. Defaulting off takes wp-admin off that path.Performance
The cold-cache performance trade-off was the open question when this PR was opened. The benchmarks on #13084 answer it for the main path into the admin: logging in with an empty browser cache. They compare today's default (concatenation on) with this PR's configuration (concatenation off, with r64120's prefetching), and with concatenation off and nothing prefetched as a control. Medians, with prefetching relative to today's default:
loadFull method and raw numbers: login → Dashboard (10 runs per arm) and login → Dashboard → Posts list → block editor (3 runs per arm).
Turning concatenation off with prefetching is faster than today's default because a concatenated bundle is only reused when its exact list of handles matches. The Posts list and the editor each build bundles that differ from the Dashboard's, so they download the common admin CSS and jQuery again, while individual files carry over from screen to screen. The login screen's higher
loadtime comes from concatenation being off there, not from the prefetching, and its FCP barely moves.What the benchmarks do not cover:
Notes about TinyMCE
TinyMCE is now always registered as separate files: TinyMCE core (
wp-tinymce-root) and the compat3x plugin (wp-tinymce). When an editor is initialized, TinyMCE fetches its theme, plugins and skin itself. The prebuiltwp-tinymce.jsbundle is no longer registered.Until now, the bundle was registered only when scripts were both concatenated and compressed. Concatenation is now off by default.
$compress_scriptshasn't compressed anything since r43580 and r44651, and it is slated for removal (Core-66053). So TinyMCE's registration no longer depends on either. The second parameter ofwp_register_tinymce_scripts()is unused, so it is deprecated and renamed to$deprecated. A site that wants the bundle can still register it under thewp-tinymcehandle:The bundle holds TinyMCE core, the modern theme and all 22 plugins: 671 KB, versus 369 KB for core plus compat3x. Whether leaving it out helps depends on whether TinyMCE is initialized.
Loaded but not initialized: smaller and faster. The block editor loads TinyMCE on every screen. It initializes TinyMCE only when a Classic block's "Edit" button is clicked, even if the post already contains a Classic block. Block editor page load, before any click:
loadInitialized: slower. This covers the classic editor, and a Classic block once "Edit" is clicked:
loadThe bytes are about the same: 233 KB versus 228 KB of TinyMCE in the classic editor, over 20 more requests. The delay comes from the order the files load in. Once its core has run, TinyMCE requests the rest in three rounds, each waiting for the last:
With the bundle, the "Edit" click needs 2 requests (27 KB). Without it, the click needs 21 requests (127 KB).
TinyMCE is being phased out, so this cost is accepted. It could be reduced by registering the theme and plugins as their own handles and enqueuing them where the classic editor initializes TinyMCE. They would then load from the page's HTML instead of waiting for TinyMCE to request them. That would not help the Classic block, which only fetches them when "Edit" is clicked.
Method: medians of 5 cold-cache runs per arm, run alternately, with a real login each run. Chrome over HTTP/1.1 on localhost with DevTools throttling, concatenation and
SCRIPT_DEBUGoff, all plugins disabled. HTTP/2 should shrink the cost of the extra requests.Testing instructions
CONCATENATE_SCRIPTSnorSCRIPT_DEBUGdefined inwp-config.php.load-scripts.phporload-styles.php— every handle appears as its own<script src>or<link href>.tinymce.min.jsandplugins/compat3x/plugin.min.js, followed by the modern theme and the editor plugins as separate requests, with nowp-tinymce.js. Do the same in the classic editor (e.g. with the Classic Editor plugin active), confirming the Visual tab works.wp-login.phpand view source. There should be<link rel="prefetch">tags for the admin's stylesheets and head scripts near the end of the page, since the login screen now predicts that the admin will not concatenate.define( 'CONCATENATE_SCRIPTS', true );towp-config.phpand reload the same screens. Bothload-scripts.phpandload-styles.phpshould reappear on the admin screen, confirming the opt-in path still works, and the login screen should print no prefetch links. TinyMCE should still load as separate files, not aswp-tinymce.js.Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5, Claude Opus 5.5
Used for: Making the change, running the test suite and confirming the pre-existing failures against baseline, and drafting this description. Reviewed by me.
The merge with trunk after r64120, moving the change into
wp_should_concatenate_admin_scripts()and updating its tests and this description (including the performance summary from the #13084 benchmarks), was done by @westonruter with Claude Code (Claude Opus 5.5).Always registering TinyMCE as separate files, deprecating the second parameter of
wp_register_tinymce_scripts(), benchmarking TinyMCE with and without the bundle, and the matching updates to this description were also done by @westonruter with Claude Code (Claude Opus 5.5).