Skip to content

Performance: 20x fewer field-lookup queries, screen-gated heavy assets, 4MB lighter zip#466

Draft
cbravobernal wants to merge 9 commits into
trunkfrom
perf/runtime-and-asset-optimizations
Draft

Performance: 20x fewer field-lookup queries, screen-gated heavy assets, 4MB lighter zip#466
cbravobernal wants to merge 9 commits into
trunkfrom
perf/runtime-and-asset-optimizations

Conversation

@cbravobernal

Copy link
Copy Markdown
Contributor

Stalled until 2026-06-15 (Mon). Do not merge before then. Supersedes #451, which was auto-closed when its base branch (the test battery) merged into trunk.

Implements the highest-impact, lowest-risk items from a measured performance audit. All changes are behavior-identical: the full battery (PHPUnit / Jest / E2E / PHPStan) passes without modifying a test.

PHP runtime

  • Prime sibling field definitions when a field key resolves (includes/acf-field-functions.php): get_field() over a 50-field template drops from ~101 SQL queries / ~17ms to ~5 / ~2.8ms on cache-less hosts. Opt-out via acf/prime_field_group_fields.
  • Decode each local JSON file once per request instead of 4× (includes/local-json.php): ~44ms → ~16ms at 200 files.
  • Per-request cache for acf_get_option_meta() with invalidation via core option hooks. (Note: this PR keeps the esc_like() escaping that landed on trunk in Use esc_like() when building option-meta LIKE patterns #462 — the cache wraps that hardened query, it does not revert it.)
  • acf_decode_taxonomy_term(): raw SQL → get_term().
  • Blocks save-path early bail when no block types are registered.
  • Gate the escaped-html notice script to when the notice renders.
  • Memoize the WP version check in acf_is_using_datastore().

Assets / enqueue

  • scf-bindings moved to enqueue_block_editor_assets (was pulling the wp-editor stack onto classic admin + front-end acf_form pages).
  • Command-palette scripts gated on wp-commands being enqueued.
  • Drop wp-polyfill from all handles (webpack injectPolyfill).
  • Fix pro CSS min suffix (production was shipping unminified CSS).
  • Gate acf-pro-ui-options-page with is_admin().
  • Fix acf-dark stylesheet 404.
  • Trim release zip (exclude assets/src + source maps): −4.2 MB.

Verification (on this branch, merged up to current trunk)

Use of AI Tools

Authored by Claude Code (Claude Fable 5) under human direction.

cbravobernal and others added 9 commits June 12, 2026 01:40
PHPUnit 2261 -> 2788 tests (+527, +2074 assertions) covering previously
untested flows: public template API (get_field/update_field/have_rows row
API), upgrade migrations, revision save/restore, local JSON/fields/meta,
Meta storage backends, ACF_Data, validation, options pages, abilities
(incl. schema-robustness repros), blocks PHP (registration/render/
bindings), AJAX handlers, Site Health, and misc functions.

Jest 772 -> 946 tests (+174) for the hooks system, core utilities,
serialization, the legacy compatibility layer, and unload warnings.

E2E: +4 tests (options page UI lifecycle, field group duplication, user
profile fields), a REST purge utility plugin for suite isolation, and
fixes for two order/timing-dependent specs (abilities-fields, url
preview race).

Known-behavior findings are documented in-test with NOTE comments and
left unfixed to keep this change purely additive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… screens

PHP runtime (measured in wp-env, cache-less host):
- Prime sibling field definitions when a field key resolves: get_field()
  across a 50-field template drops from 101 SQL queries / ~17ms to
  5 queries / ~2.8ms. Opt-out via acf/prime_field_group_fields filter;
  per-field load_field filters unchanged.
- Decode each local JSON file once per request instead of 4x:
  44ms -> 16ms at 200 files.
- Per-request cache for acf_get_option_meta() LIKE queries, invalidated
  via core added/updated/deleted_option hooks.
- acf_decode_taxonomy_term(): raw term_taxonomy SQL -> get_term().
- Early-bail block save parsing when no block types are registered.
- Enqueue the escaped-html notice script only when the notice renders.
- Memoize the WP version check in acf_is_using_datastore().

Assets:
- Load scf-bindings only in block editor contexts; it previously pulled
  the full wp-editor dependency stack onto classic admin pages and
  public front-end acf_form() pages.
- Gate command-palette scripts on wp-commands being enqueued (stops
  React + wp-components loading on every classic admin page on WP <=6.8).
- Drop wp-polyfill dependency from all bundles (webpack injectPolyfill).
- Fix pro CSS min suffix: production shipped unminified acf-pro-input.css.
- Gate admin-only acf-pro-ui-options-page script with is_admin().
- Fix acf-dark stylesheet 404 (wrong path since the build move).
- Exclude assets/src and source maps from the release zip (-4.2MB).

Verified: 2788 PHPUnit / 946 Jest / 253 E2E tests green, PHPStan clean,
zero tests modified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PHP 7.4 raises E_NOTICE for undefined array keys (PHP 8 raises
E_WARNING) and the notice is not converted to a Throwable, so the
try/catch capture never fired. Capture via an explicit error handler
covering both error types instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review feedback: tests that assert possible-bug behavior as green
expectations now reference the GitHub issues tracking each finding
(#453-#461), so future fixes read as intentional, not regressions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…est.step structure

- scf-test-get-field-user.php reads ?scf_test_user_id (absint-validated),
  falling back to the queried author, removing the user_1 assumption;
  user-profile-fields.spec.ts derives the real admin ID via /users/me.
- Purge endpoint renamed to /purge-internal-posts to match what it
  deletes; single shared purgeScfInternalPosts() helper in
  field-helpers.js replaces four duplicated copies.
- Large lifecycle tests restructured with test.step() (duplication,
  options page, post-type integration flow) with small local helpers
  for repeated workflows; assertions unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seeded, CI-reproducible fuzz/property tests (SCF_FUZZ_ITERATIONS to crank
locally; failing seed + input embedded in assertion messages):

- PHP (tests/php/includes/fuzz/): post-id decoding, value round-trips,
  validation, the JSON schema validator, local JSON file ingestion,
  block.json registration, and escaping/sanitization helpers — including
  a security property that acf_maybe_unserialize() never instantiates
  real objects (verified: object-injection payloads decode only to
  __PHP_Incomplete_Class placeholders).
- JS (tests/js/fuzz/): acf.serialize, flexible-content normalization,
  and escaping utilities under a seeded PRNG.

Adds 27 PHPUnit + 5 Jest tests (~3s). Crashes surfaced on hostile input
are documented in-test with NOTE comments (generators constrained) and
reported for follow-up issues; no source was modified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…et-optimizations

# Conflicts:
#	tests/php/includes/fuzz/test-fuzz-schema-validator.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant