Skip to content

[6.x] Allow static cache JS to be externalized - #15342

Open
ryanmitchell wants to merge 1 commit into
statamic:6.xfrom
ryanmitchell:feature/nocache-csp
Open

[6.x] Allow static cache JS to be externalized#15342
ryanmitchell wants to merge 1 commit into
statamic:6.xfrom
ryanmitchell:feature/nocache-csp

Conversation

@ryanmitchell

@ryanmitchell ryanmitchell commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #8802.

Background

Full-measure (file) static caching injects two small inline <script> blocks into every cached page — one to swap the placeholder CSRF token, one to hydrate nocache regions. A site sending Content-Security-Policy: script-src 'self' blocks inline scripts, so full static caching can't be used with that policy.

What this does

Adds a script_delivery option to config/static_caching.php:

'script_delivery' => env('STATAMIC_STATIC_CACHING_SCRIPT_DELIVERY', 'inline'),
  • inline (default) — unchanged behaviour, byte-identical output.
  • external — the snippets are served from same-origin routes and referenced with <script src="…">, which satisfies script-src 'self' with no nonce or hash.

The two routes (statamic.nocache.js, statamic.csrf.js, under the action-route prefix) are only registered when script_delivery is external. They respond with application/javascript and an ETag.

The script tag is a publishable view

The JS snippets moved out of heredocs in FileCacher into Blade views, and the <script> tag itself is now a view too:

static-caching/csrf-js.blade.php: CSRF snippet body
static-caching/nocache-js.blade.php: nocache snippet body
static-caching/script.blade.php: the <script> tag wrapper (shared by both)

publishable using: php artisan vendor:publish --tag=statamic-static-caching

script.blade.php is where you'd add a nonce or integrity attribute for a stricter policy, for example:

@if ($inline)<script nonce="{{ request()->attributes->get('csp_nonce') }}">{!! $contents !!}</script>
@else<script nonce="{{ request()->attributes->get('csp_nonce') }}" src="{{ $src }}"></script>@endif

The tag is rendered during the cache-miss request, so any per-request/per-cache value your middleware has set is available — no new Statamic API needed. The existing StaticCache::nocacheJs() / csrfTokenJs() overrides still work.

Backwards compatibility

Default is inline; existing sites see identical output. No breaking changes.

@ryanmitchell ryanmitchell changed the title [6.x] Allow static cache CS to be externalized [6.x] Allow static cache JS to be externalized Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NoCacheReplacer and CSP headers

1 participant