Skip to content

fix(newspack-plugin): cache-bust assets by content hash#290

Open
dkoo wants to merge 15 commits into
mainfrom
fix/newspack-plugin-asset-content-hash
Open

fix(newspack-plugin): cache-bust assets by content hash#290
dkoo wants to merge 15 commits into
mainfrom
fix/newspack-plugin-asset-content-hash

Conversation

@dkoo

@dkoo dkoo commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

All Submissions:

Changes proposed in this Pull Request:

WP-admin (and some reader-facing) JS/CSS assets emitted by Newspack Plugin can go stale at the CDN even after a new build is deployed. Previously every enqueue passed NEWSPACK_PLUGIN_VERSION as the ver query string, which only bumps on release — so alpha builds, hotfixes, and same-version redeploys all reused the same URL and inherited the previous cache entry. (Atomic edges do honor ?ver=; the failure mode was the version not changing, not query-string stripping.)

Webpack already emits a per-bundle content hash into dist/<name>.asset.php (via @wordpress/dependency-extraction-webpack-plugin). This PR introduces a small helper that reads it and routes every dist-asset enqueue through it, so ?ver= changes whenever the bundle bytes change — independent of the plugin version.

  • New helper: Newspack::asset_version( string $name ): string — memoized per request, reads dist/<name>.asset.php, falls back to NEWSPACK_PLUGIN_VERSION when missing or malformed. 5 unit tests, including deterministic fixtures so the suite is environment-independent and CI-safe (works even when dist/ is absent on the runner).
  • ~55 enqueue call sites converted across includes/ and src/blocks/. Each swap matches the asset URL on the same call and matches the file's existing Newspack:: / \Newspack\Newspack:: qualification style.
  • Incidental fixes found during the sweep:
    • class-major-revisions.php had a pre-existing malformed wp_register_style() call (version constant in deps position, true as version). Now deps=[], version=helper.
    • trait-wizards-admin-header.php had a raw include of admin-header.asset.php with no file_exists guard. The helper supersedes it; the include is removed.
    • class-wizard.php had a stale $asset_file = include … whose value was never read. Removed.
    • Same-handle inconsistency fixed: newspack-blocks-frontend (dist/blocks.css) is registered from two files; both now agree on the content hash.
  • Intentionally not changed: class-handoff-banner.php enqueues a raw /src/wizards/handoff-banner/block-editor.js (no .asset.php exists for it) — keeps NEWSPACK_PLUGIN_VERSION. The helper's fallback handles the same case automatically everywhere else.

Future improvement deferred to a follow-up: moving entries to content-hashed filenames (wizards.[contenthash].js) so URL paths themselves change. Atomic respects ?ver=, so this PR is expected to fully resolve the symptoms on our fleet; hashed filenames would only add robustness on publisher-fronted third-party CDNs configured to ignore query strings.

Sibling plugins (newspack-blocks, newspack-popups, newspack-newsletters, newspack-ads, newspack-network) almost certainly have the same code shape and should get the same treatment in follow-up PRs.

Closes #

How to test the changes in this Pull Request:

  1. Spin up an isolated env on this branch and activate Newspack Plugin:
    • n env create cachebust --worktree newspack-plugin:fix/newspack-plugin-asset-content-hash --domain cachebust.local
    • n env up cachebust --build
    • n setup --env cachebust --yes (optional, for a fully bootstrapped site)
  2. Helper sanity check (run inside the env container):
    docker exec newspack_env_cachebust sh -c "wp eval 'echo Newspack\\Newspack::asset_version(\"commons\"), PHP_EOL, Newspack\\Newspack::asset_version(\"wizards\"), PHP_EOL, Newspack\\Newspack::asset_version(\"nope-does-not-exist\"), PHP_EOL;' --allow-root"
    
    Expect two 20-char hex hashes for commons and wizards matching the version in their respective dist/*.asset.php files; the missing asset returns the plugin version (e.g. 6.42.4).
  3. Rendered URL check (frontend): load https://cachebust.local/ and view source. Search for any newspack-plugin/dist/.../*.js or .css URL — every ?ver=… should be a 20-char hex hash, not a semver string. Reader-facing assets to grep for: reader-activation.js, reader-auth.js, newsletters-signup.js, newspack-ui.js, content-banner.js, content-gate-countdown-block.js, reader-registration-block.js.
  4. Rendered URL check (admin): log in to https://cachebust.local/wp-admin/ and load:
    • admin.php?page=newspack-dashboardwizards.js, commons.js, admin.css, admin-header.js/.css all carry hashes.
    • admin.php?page=newspack-setup-wizardsetup.js/.css hashed.
    • admin.php?page=newspack-newsletters-wizardnewsletters.js hashed.
    • admin.php?page=advertising-display-ads (or similar advertising page) — billboard.js/.css hashed.
    • The WP Plugins screen — plugins-screen.js/.css hashed.
  5. Cache-busting actually works (the core promise of this PR): edit any source file under plugins/newspack-plugin/src/wizards/, rebuild (n build newspack-plugin from the workspace root), reload the dashboard, and confirm the ?ver=… for wizards.js changes to a different hash. Without rebuilding, the hash should stay the same across reloads (deterministic).
  6. Missing-build fallback: temporarily move dist/ aside inside the container, reload any admin page — every ?ver= should fall back to the plugin's semver. Move dist/ back.
    docker exec newspack_env_cachebust sh -c "mv /newspack-plugins/newspack-plugin/dist /newspack-plugins/newspack-plugin/dist-bak"
    # reload, then:
    docker exec newspack_env_cachebust sh -c "mv /newspack-plugins/newspack-plugin/dist-bak /newspack-plugins/newspack-plugin/dist"
    
  7. PHPUnit suite: docker exec newspack_env_cachebust /var/scripts/test-php.sh newspack-plugin → expect 1499 tests, 1 unrelated skip, no failures. Includes 5 new tests in tests/unit-tests/asset-version.php.
  8. CI-safe tests check: simulate an unbuilt CI runner and confirm the new tests still pass:
    docker exec newspack_env_cachebust sh -c "mv /newspack-plugins/newspack-plugin/dist /newspack-plugins/newspack-plugin/dist-bak && cd /newspack-plugins/newspack-plugin && phpunit --filter Newspack_Test_Asset_Version; rm -rf /newspack-plugins/newspack-plugin/dist; mv /newspack-plugins/newspack-plugin/dist-bak /newspack-plugins/newspack-plugin/dist"
    
    Expect: 3 pass, 2 skip (the real-build tests skip cleanly when no dist/ is present).
  9. Reader flows still work end-to-end: open an incognito tab against the env, trigger a reader-auth modal (e.g. attempt to register), submit a newsletter signup. Frontend scripts must load and function — these depend on reader-activation, reader-auth, newsletters-signup, newspack-ui. No JS console errors related to handle/dependency mismatches.
  10. Admin flows still work end-to-end: click through the Newspack dashboard tabs (Audience, Advertising, Newsletters, Settings). No 404s on any dist/*.js/.css; no console errors.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully run tests with your changes locally?

dkoo and others added 12 commits June 11, 2026 16:07
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… hash

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 11, 2026 23:16

Copilot AI left a comment

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.

Pull request overview

This PR improves cache-busting for Newspack Plugin JS/CSS assets by using the content-hash version emitted into dist/*.asset.php (instead of relying solely on NEWSPACK_PLUGIN_VERSION), and updates enqueue call sites accordingly to prevent stale CDN-cached assets across redeploys.

Changes:

  • Add Newspack::asset_version( string $name ): string to resolve per-asset hashed versions from dist/<name>.asset.php, with fallback to NEWSPACK_PLUGIN_VERSION.
  • Convert numerous script/style enqueues across admin, frontend, wizards, and integrations to use the new helper for the ver argument.
  • Add PHPUnit coverage for the helper, including fixtures and “missing/malformed asset file” fallbacks.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
plugins/newspack-plugin/includes/class-newspack.php Adds asset_version() helper and applies it to common assets.
plugins/newspack-plugin/tests/unit-tests/asset-version.php Adds unit tests covering helper behavior (valid, malformed, missing, nested paths).
plugins/newspack-plugin/src/blocks/reader-registration/index.php Switch block JS/CSS versioning to asset_version().
plugins/newspack-plugin/src/blocks/my-account-button/class-my-account-button-block.php Switch blocks CSS versioning to asset_version().
plugins/newspack-plugin/src/blocks/content-gate/countdown/class-content-gate-countdown-block.php Switch countdown block script versioning to asset_version().
plugins/newspack-plugin/includes/wizards/traits/trait-wizards-admin-header.php Replace direct .asset.php include with asset_version() for admin-header assets.
plugins/newspack-plugin/includes/wizards/newsletters/class-newsletters-wizard.php Switch wizard script versioning to asset_version().
plugins/newspack-plugin/includes/wizards/class-wizard.php Switch wizards bundle versioning to asset_version() and remove unused include.
plugins/newspack-plugin/includes/wizards/class-setup-wizard.php Switch setup wizard JS/CSS versioning to asset_version().
plugins/newspack-plugin/includes/wizards/class-components-demo.php Switch components demo script versioning to asset_version().
plugins/newspack-plugin/includes/wizards/audience/class-audience-wizard.php Switch content-banner preview CSS versioning to asset_version().
plugins/newspack-plugin/includes/wizards/audience/class-audience-content-gates.php Switch content-banner preview CSS versioning to asset_version().
plugins/newspack-plugin/includes/wizards/advertising/class-advertising-sponsors.php Switch billboard CSS versioning to asset_version().
plugins/newspack-plugin/includes/wizards/advertising/class-advertising-display-ads.php Switch billboard JS/CSS versioning to asset_version().
plugins/newspack-plugin/includes/revisions-control/class-major-revisions.php Fix wp_enqueue_style() args and switch revisions-control assets to asset_version().
plugins/newspack-plugin/includes/reader-activation/class-reader-activation.php Switch reader-activation/auth/newsletters-signup assets to asset_version().
plugins/newspack-plugin/includes/polyfills/class-amp-polyfills.php Switch lightbox assets to asset_version() (nested dist path).
plugins/newspack-plugin/includes/plugins/woocommerce/my-account/class-woocommerce-my-account.php Switch my-account script versioning to asset_version().
plugins/newspack-plugin/includes/plugins/woocommerce/my-account/class-my-account-ui-v1.php Switch v1 account assets to asset_version().
plugins/newspack-plugin/includes/plugins/woocommerce/my-account/class-my-account-ui-v0.php Switch v0 account CSS versioning to asset_version().
plugins/newspack-plugin/includes/plugins/woocommerce/class-woocommerce-products.php Switch custom product options script versioning to asset_version().
plugins/newspack-plugin/includes/plugins/woocommerce/class-woocommerce-cover-fees.php Switch cover-fees script versioning to asset_version().
plugins/newspack-plugin/includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-settings.php Switch group subscription admin assets to asset_version().
plugins/newspack-plugin/includes/plugins/co-authors-plus/class-nicename-change-ui.php Switch nicename-change assets to asset_version().
plugins/newspack-plugin/includes/plugins/co-authors-plus/class-guest-contributor-role.php Switch co-authors-plus admin script versioning to asset_version().
plugins/newspack-plugin/includes/plugins/class-organic-profile-block.php Switch organic profile block CSS versioning to asset_version().
plugins/newspack-plugin/includes/optional-modules/class-nextdoor.php Switch nextdoor editor assets to asset_version().
plugins/newspack-plugin/includes/emails/class-emails.php Switch emails editor assets to asset_version().
plugins/newspack-plugin/includes/corrections/class-corrections.php Switch corrections assets to asset_version().
plugins/newspack-plugin/includes/content-gate/class-content-gate.php Switch content-banner JS/CSS versioning to asset_version().
plugins/newspack-plugin/includes/content-gate/class-block-patterns.php Switch block-patterns CSS versioning to asset_version().
plugins/newspack-plugin/includes/collections/class-enqueuer.php Switch collections script/style versioning to asset_version().
plugins/newspack-plugin/includes/class-salesforce.php Switch salesforce script versioning to asset_version().
plugins/newspack-plugin/includes/class-recaptcha.php Switch reCAPTCHA assets to asset_version().
plugins/newspack-plugin/includes/class-newspack-ui.php Switch newspack-ui JS/CSS versioning to asset_version().
plugins/newspack-plugin/includes/class-handoff-banner.php Switch handoff-banner CSS versioning to asset_version().
plugins/newspack-plugin/includes/class-blocks.php Switch blocks editor/frontend assets to asset_version().
plugins/newspack-plugin/includes/class-admin-plugins-screen.php Switch plugins screen assets to asset_version().
plugins/newspack-plugin/includes/bylines/class-bylines.php Switch bylines editor assets to asset_version().

Comment thread plugins/newspack-plugin/includes/class-newspack.php
@dkoo dkoo self-assigned this Jun 11, 2026
@dkoo dkoo marked this pull request as ready for review June 12, 2026 16:24
@dkoo dkoo requested a review from a team as a code owner June 12, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants