Repository navigation
Trim the packaged app by about 350 MB: unused PHP builds, renderer libraries and Chromium locales - #707
Merged
Conversation
…mium locales Three things the app shipped and never loads: - The asyncify PHP builds. Every @php-wasm/node-* package carries each PHP version as jspi/ and asyncify/, and reads asyncify/ only when the runtime lacks WebAssembly.Suspending. Electron 43.6.0 has it. PHP 5.2, which the app does not offer, goes with them. - The renderer's libraries. React, Emotion, xterm and the @WordPress UI packages are bundled into src/renderer/index.js by esbuild, but sat in dependencies, so electron-builder copied their trees into app.asar too. They move to devDependencies; @wordpress/i18n and @wordpress/hooks stay, because the main process loads them. The 22 build.files exclusions that kept part of that tree out are no longer needed. - Chromium's locales for languages the app has no catalog for. The app shows English for those anyway, so build.electronLanguages keeps English and the languages in src/languages. The unsigned macOS arm64 app goes from 920 MB to 571 MB, 320 MB to 218 MB zipped. Two unit tests guard the cuts: one asks the bundled Electron for JSPI, the other fails when a catalog's Chromium locale is not kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Electron 43's npm package has no install script: the first
`require('electron')` downloads and unpacks the binary. CI's unit job
reaches that during `npm test`, and with three test files now asking at
once, each started its own download and read a half-unpacked
Electron.app (ENOENT on the framework's Resources, dyld unable to load
the framework). A `pretest` script asks once, before `node --test` runs
the files in parallel. The languages test also asks before reading
dist/, so it holds when run on its own from a fresh clone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build.electronLanguages was a hand-written list, and a test only told whoever ran `npm run i18n:download` which entries to add. That test also asked for the wrong locale for a regional Spanish catalog: es where Chromium loads es-419. scripts/chromium-locales.cjs now maps a catalog to the Chromium locale Chromium itself would load, with its regional folding (es-419, pt-PT, zh-TW, en-GB) on top of slugTag's aliases, and builds the list: English, then each locale in both spellings, `pt-BR` for Windows and Linux and `pt_BR` for macOS. The download writes it into package.json from every catalog it leaves, only when it changes; a JSON round trip gives the file back byte for byte, so the list is the whole diff. The test now asserts the list equals the computed one, which also catches a stale entry, and that electron-builder keeps every file the list names. Run against translate.wordpress.org today, it adds sr and tr for the two catalogs above the cut-off that the repository does not have yet, and leaves out lo, which Chromium has no locale for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A missing Electron binary is downloaded on the first require; failing there after the catalogs were replaced left the run half applied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#704 asks that every @php-wasm/node-X-Y package whose version SupportedPHPVersions does not report stay out of the app. Today that is node-5-2 alone, excluded by name. A Playground update that drops a version from the list or ships another legacy one would change which names those are; this test then names the build.files exclusion to add or to remove. Fixes #704. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ryanwelcher
approved these changes
Oct 21, 2026
ryanwelcher
left a comment
Collaborator
There was a problem hiding this comment.
Great work! I've compared builds in buildkite and the artifacts are much smaller
Merged
ryanwelcher
added a commit
that referenced
this pull request
Oct 23, 2026
## Why `v2.0.0-beta.1` shipped on 13 October. Ten commits have reached trunk since then (#667 to #707), and milestone `v2.0.0` has 8 closed issues and none open. This is a stable release: it takes `releases/latest` from `v1.2.1`. `electron-builder` names the artifacts after `package.json`, so the version has to move before the tag and artifacts exist. ## What changes - **The version.** The three root version fields in `package.json` and `package-lock.json` move from `2.0.0-beta.1` to `2.0.0`. No dependency versions change. - **Translations.** `npm run i18n:download` refreshed the seven existing catalogs and added `lo`, `sr` and `tr`. None was removed, and no right-to-left locale was held back. - **Chromium locales.** Since #707 the same script keeps `build.electronLanguages` in line with the shipped catalogs, so it added `sr` and `tr` there. `lo` has no Chromium locale of its own. | Locale | Translated | Strings | | --- | --- | --- | | cs | 94% | 1037 | | en-ca | 95% | 1050 | | en-gb | 100% | 1100 | | gl | 96% | 1066 | | hu | 95% | 1050 | | lo | 95% | 1050 | | nl | 100% | 1100 | | pl | 99% | 1090 | | sr | 100% | 1100 | | tr | 100% | 1100 | ## How to test this **Platforms:** any for steps 1 to 3. Step 4 needs macOS for `Info.plist` and Windows for the `.exe`. Steps 4 and 5 use the Buildkite build for the current head. **Starting state:** this branch checked out with `node_modules` installed. Run every command from the repository root. 1. `npm run lint` is clean and `npm test` passes. 2. `node -e "console.log(require('./package.json').version)"` prints `2.0.0`. 3. `python3 -c "import json;d=json.load(open('package-lock.json'));print(d['version'], d['packages']['']['version'])"` prints `2.0.0 2.0.0`. 4. On the Buildkite build for the current head, the artifacts are named `wordpress-contributor-toolkit-2.0.0-*`. The `app.asar` root holds exactly `node_modules`, `package.json` and `src`, with npm 11 under `node_modules/npm` and no `.codesigning`. On macOS, `CFBundleShortVersionString` reads `2.0.0`. 5. In the installed app, set the language to Turkish in the settings and relaunch. The interface is in Turkish. **What must not have happened:** no dependency version may change. `git diff trunk -- . ':!src/languages'` shows five changed lines: the three root version fields and the two new `electronLanguages` entries. ## Risks and limitations None known. RELEASING.md still says to expect exactly three changed lines outside `src/languages/`. Since #707 a release that adds a locale with a Chromium locale changes `electronLanguages` too. #710 rewrites RELEASING.md and can update that line. ## Related Milestone `v2.0.0`. Release notes follow on the release. --- <details> <summary>Review outcome (required — see AGENTS.md)</summary> 0 [fix here] · 0 [follow-up]. Automatic checks only, as in #681: this change has no logic to review. - **Review:** completed, deterministic layer, in session; head `9df142b` / base `630253f` (trunk). `npm run lint` passes, `npm test` passes (2214 tests, 0 failures, 2 skipped), both files are valid JSON, and the diff outside `src/languages/` is the three root version fields plus the two `electronLanguages` entries. Outcome: nothing to fix. - **Since review:** none. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ryanwelcher
added a commit
that referenced
this pull request
Oct 23, 2026
- Allow the build.electronLanguages lines in the bump diff, which i18n:download rewrites since #707. - Check the signatures in section 2: codesign, spctl and stapler on macOS, and the Authenticode certificate of the Windows installer. - Say that Buildkite reports nothing to the pull request, so the person confirms the build's commit. - Merge with --match-head-commit, and let the skill merge when the person asks. - Check the docs site's Download button from a new tab, since it keeps the release it read for the tab's session.
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.
Why
The packaged app is about 920 MB on disk on macOS (320 MB zipped), and about a third of that is code it never loads. That is a long download on a Contributor Day network, where everyone fetches the app at the same time. It is the same problem #23 reported. That PR has since gone stale against trunk, and its claim that
@xterm/xtermis unused no longer holds, so this branch starts again from trunk.What changes
Three things the app ships and never loads are left out:
@php-wasm/node-*package carries every PHP version twice, asjspi/and asasyncify/, and@php-wasm/nodereadsasyncify/only when"Suspending" in WebAssemblyis false. Electron 43.6.0 has JSPI, so those folders never load.@php-wasm/node-5-2goes too, because the app offers onlySupportedPHPVersions(7.4–8.5). Both arebuild.filesexclusions;node_modulesis untouched.app.asar. esbuild already bundles React, Emotion, xterm and the@wordpressUI packages intosrc/renderer/index.js, but they were listed independencies, so electron-builder copied their trees in as well. They move todevDependencies.@wordpress/i18nand@wordpress/hooksstay, because the main process loads them. The 22 hand-keptbuild.filesexclusions that trimmed part of that tree since Update @wordpress/components from 28 to 41 as the base for the design system redesign #563 are now unnecessary and are removed.build.electronLanguageskeeps English and the Chromium locale of each catalog insrc/languages.npm run i18n:downloadnow writes that list whenever it adds or removes a catalog, so the version-bump PR carries the change with no manual step.scripts/chromium-locales.cjsmaps a catalog to the locale Chromium itself would load, including Chromium's regional folding (es-mx→es-419,pt→pt-PT,zh-hk→zh-TW,en-ca→en-GB). Every regional locale is written in both spellings,pt-BRfor Windows and Linux andpt_BRfor macOS, because electron-builder matches file names.Unit tests guard the cuts:
electron-wasm-jspiasks the bundled Electron forWebAssembly.Suspending, so an Electron bump that loses JSPI fails CI instead of the first dev server start.electron-languagesasserts that the list equals the one the catalogs call for, which catches both a missing entry and a stale one. It also checks that electron-builder keeps every locale file the list names.chromium-localescovers the mapping with both platforms' locale names.php-buildsfails when an installed@php-wasm/node-X-Ywhose versionSupportedPHPVersionsdoes not offer would ship, and when a version the settings offer is excluded.Run against translate.wordpress.org today, the script adds
srandtrfor two catalogs that are above the cut-off but not yet in the repository, and leaves outlo, which Chromium has no locale for.Not in this PR: dropping PHP versions the settings offer (a product decision since #559), and the
intlextension and ICU data, which core's tests use.node_modules.appon diskapp.asarapp.asar.unpackedHow to test this
Platforms: macOS and Windows, both needed, because the PHP runtime is chosen when the server starts and no CI job starts the real Playground server (see the Electron pin note in AGENTS.md). Use the Buildkite artifact for the current head commit.
Starting state: the app from this branch's Buildkite build, with a site that has finished setup and whose server is stopped.
/wp-admin/both load in the browser.Cannot find moduleerror, and no path containingasyncify.node_modulesfor any of it.What must not have happened:
Risks and limitations
electron-wasm-jspiguards.cs_FEMININE.lprojand similar) for the kept languages; each holds an 18-bytelocale.pak. Chromium should fall back to the base locale, but I have not checked a macOS user with a grammatical gender set.electron-languagescopies electron-builder's matching rule, because it is not exported. An electron-builder release that changes that rule would not be caught.scripts/chromium-locales.cjsfollowCheckAndResolveLocalein Chromium'sl10n_util.cc, but no Chromium source is vendored here to check them against. Onlyen-ca→en-GBaffects today's list, anden-GBis kept foren-gbanyway.npm run i18n:downloadnow needs an installed Electron, which it downloads on first use. It reads Electron's locales before changing any catalog, so a failed download leaves everything as it was.--user-data-diradded to its launch, because a dev copy of the app held the single-instance lock. Trunk's build failed the same way without it. CI's run on this PR is the unmodified one.Related
asyncify/folder of every PHP build is left out, which is the exclusion the issue proposes, andelectron-wasm-jspiguards the JSPI it depends on.@php-wasm/node-5-2, the only installed build whose versionSupportedPHPVersionsdoes not report, is left out.php-buildsfails when a Playground update changes which builds those are, and names the exclusion to add or remove.build.electronLanguageskeeps only English and the Chromium locales of the app's catalogs, andnpm run i18n:downloadkeeps it in step.Design decisions and alternatives considered
build.files, not apostinstallprune.node_modulesstays complete for development, the tests and the journeys. Only what electron-builder copies changes.devDependenciesrather than more!node_modules/...lines. The exclusion list from Update @wordpress/components from 28 to 41 as the base for the design system redesign #563 had to grow every time a@wordpresspackage gained a dependency. Moving the cause leaves nothing to maintain, and lets 22 lines go.electronLanguageslist with a test, rather than one generated at build time. A generated list would need a JS build config or a hook; a static list plus a test that names the missing entry is simpler, and changes only when a catalog is added.Review outcome (required — see AGENTS.md)
0 [fix here] · 0 [follow-up]. One style note was applied: the
electron-languagesheader claimed Chromium's strings follow the app's language, but they follow the operating system's..github/instructions/code-review.instructions.md. Reviewed heada7be033against base2dda92c(origin/trunk). Evidence:npm run lintpassed;npm testpassed with 2202 tests, 2200 pass, 0 fail, 2 skipped;npm run test:electronpassed with 2202 tests, 2201 pass, 0 fail, 1 skipped. The five dimensions found nothing. Specifically checked: no main-process, preload or runner import of a moved package; no production dependency still reaching a formerly excluded package; asyncify reached only when JSPI is absent, including for intl and xdebug; PHP 5.2 unreachable from the settings; electronLanguages against electron-builder's matching rule and the app's locale resolution.a7be033 → 7ac9e25checked. The only change is the comment wording intests/unit/electron-languages.test.cjs, and that test still passes.7ac9e25 → 8e1d005, a CI fix, re-checked by the author against the same standard: 0 findings. CI's unit job failed because Electron 43's npm package downloads its binary on the firstrequire('electron'), and three test files now asked for it at the same moment. I reproduced that locally by removingnode_modules/electron/dist: two downloads ran and two tests failed. Apretestscript now asks once beforenode --teststarts, and the workflow comment that saidnpm cifetches Electron is corrected. Run from a missing binary,npm testdownloads once and passes 2200 tests with 0 failures, andnpm run test:electronandnpm run lintpass too.8e1d005 → dde0f94(thei18n:downloadchange): completed by a separate Claude agent context against the same standard, in the context oforigin/trunk...dde0f94. Result: 1 [fix here] · 0 [follow-up], fixed in26e9250. The finding: Electron's locale names were read after the catalogs had been replaced, so a failed Electron download would leave the run half applied. They are now read before anything is written. One style note was applied as well, a test title that claimed more than it asserted. The reviewer also ran about 130 slugs through the mapping without a crash, and checked that rewritingpackage.jsonreproduces the file byte for byte. Lint passes, andnpm testandnpm run test:electroneach pass 2212 tests with 0 failures.dde0f94 → 26e9250. Only that fix and the renamed test changed; the suites above ran on26e9250.26e9250 → 55ab855adds onlytests/unit/php-builds.test.cjs, for Remove unused PHP versions #704. I checked it against the standard myself: 0 findings. Broken both ways in turn (5.2 kept, 8.3 excluded), it fails each time, and it passes as committed.npm testandnpm run test:electroneach pass 2214 tests with 0 failures.Implementation notes
electron-builder --dirwith-c.mac.identity=null -c.mac.notarize=false, run twice from the samenode_moduleswith trunk's and this branch'spackage.jsonand lockfile, then zipped withditto -c -k. Signed artifacts will differ slightly.@php-wasm/nodebooted PHP 7.4.33, 8.3.33 and 8.5.10 withintlloaded, run on the packaged binary withELECTRON_RUN_AS_NODE=1.npm run test:e2e:packagedpassed all 15 tests on the trimmed build, including the first window painting, the preload bridge, and thebuild.filesallow-list checks.devOptionaltodev. No versions change.pretestrunsnode -e "require('electron')". The electron package downloads its binary on the firstrequire, so this fetches it once beforenode --testruns its files in parallel, where concurrent downloads raced.npm run test:electronalready did this in its runner, and a single file run withnode --test <file>has nothing to race with.@php-wasm/node/index.cjs(loadNodeRuntime) and in each@php-wasm/node-X-Y/index.cjs(getPHPLoaderModuleand the extension paths).Screenshots or recording
Nothing on screen changes.
🤖 Generated with Claude Code