diff --git a/config/static_caching.php b/config/static_caching.php
index 46766739505..2af89331ea4 100644
--- a/config/static_caching.php
+++ b/config/static_caching.php
@@ -142,6 +142,23 @@
\Statamic\StaticCaching\Replacers\NoCacheReplacer::class,
],
+ /*
+ |--------------------------------------------------------------------------
+ | Script Delivery
+ |--------------------------------------------------------------------------
+ |
+ | Full measure static caching injects small @else@endif
diff --git a/routes/web.php b/routes/web.php
index cb63cae04bd..8a947c7c485 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -34,6 +34,7 @@
use Statamic\StaticCaching\NoCache\CsrfTokenController;
use Statamic\StaticCaching\NoCache\NoCacheController;
use Statamic\StaticCaching\NoCache\NoCacheLocalize;
+use Statamic\StaticCaching\NoCache\ScriptController;
Route::name('statamic.')->group(function () {
Route::group(['prefix' => config('statamic.routes.action')], function () {
@@ -109,6 +110,11 @@
Route::post('csrf', CsrfTokenController::class)
->withoutMiddleware(['App\Http\Middleware\VerifyCsrfToken', 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken', 'Illuminate\Foundation\Http\Middleware\PreventRequestForgery']);
+ if (config('statamic.static_caching.script_delivery') === 'external') {
+ Route::get('nocache.js', [ScriptController::class, 'nocache'])->name('nocache.js');
+ Route::get('csrf.js', [ScriptController::class, 'csrf'])->name('csrf.js');
+ }
+
Statamic::additionalActionRoutes();
});
diff --git a/src/Providers/AppServiceProvider.php b/src/Providers/AppServiceProvider.php
index 05bb28b501f..f9be0a7e58e 100644
--- a/src/Providers/AppServiceProvider.php
+++ b/src/Providers/AppServiceProvider.php
@@ -105,6 +105,10 @@ public function boot()
"{$this->root}/resources/views/extend/scaffolding" => resource_path('views/vendor/statamic/scaffolding'),
], 'statamic-scaffolding');
+ $this->publishes([
+ "{$this->root}/resources/views/static-caching" => resource_path('views/vendor/statamic/static-caching'),
+ ], 'statamic-static-caching');
+
$this->app['redirect']->macro('cpRoute', function ($route, $parameters = []) {
/** @var \Illuminate\Routing\Redirector $this */
return $this->to(cp_route($route, $parameters));
diff --git a/src/StaticCaching/Cachers/FileCacher.php b/src/StaticCaching/Cachers/FileCacher.php
index 2b339e40120..66d56809b18 100644
--- a/src/StaticCaching/Cachers/FileCacher.php
+++ b/src/StaticCaching/Cachers/FileCacher.php
@@ -248,102 +248,16 @@ public function setNocacheJs(string $js)
public function getCsrfTokenJs(): string
{
- $csrfPlaceholder = CsrfTokenReplacer::REPLACEMENT;
-
- $default = <<
', '', $contents); + $contents = str_replace('', $this->scriptTag($cacher).'', $contents); } $contents = str_replace('NOCACHE_PLACEHOLDER', $cacher->getNocachePlaceholder(), $contents); $response->setContent($contents); } + + private function scriptTag(FileCacher $cacher): string + { + $external = config('statamic.static_caching.script_delivery') === 'external'; + + return trim(view('statamic::static-caching.script', [ + 'inline' => ! $external, + 'src' => $external ? URL::makeRelative(route('statamic.nocache.js')) : null, + 'contents' => $external ? null : $cacher->getNocacheJs(), + ])->render()); + } } diff --git a/src/Testing/Concerns/FakesViews.php b/src/Testing/Concerns/FakesViews.php index a37766a11dc..38cd72597d4 100644 --- a/src/Testing/Concerns/FakesViews.php +++ b/src/Testing/Concerns/FakesViews.php @@ -19,6 +19,12 @@ public function withFakeViews() $this->fakeView = app(FakeViewEngine::class); $this->fakeViewFinder = new FakeViewFinder($this->app['files'], config('view.paths')); + // Keep real namespace hints (e.g. `statamic::`) resolving so that faking + // the frontend views doesn't break package views rendered as a side effect. + foreach ($originalFactory->getFinder()->getHints() as $namespace => $paths) { + $this->fakeViewFinder->addNamespace($namespace, $paths); + } + $this->fakeViewFactory = new FakeViewFactory($this->app['view.engine.resolver'], $this->fakeViewFinder, $this->app['events']); $this->fakeViewFactory->setFakeEngine($this->fakeView); foreach (array_reverse($originalFactory->getExtensions()) as $ext => $engine) { diff --git a/tests/StaticCaching/ExternalScriptDeliveryTest.php b/tests/StaticCaching/ExternalScriptDeliveryTest.php new file mode 100644 index 00000000000..6884c2205ae --- /dev/null +++ b/tests/StaticCaching/ExternalScriptDeliveryTest.php @@ -0,0 +1,76 @@ +set('statamic.static_caching.strategy', 'full'); + $app['config']->set('statamic.static_caching.strategies.full.path', $this->dir = __DIR__.'/static'); + $app['config']->set('statamic.static_caching.script_delivery', 'external'); + + File::delete($this->dir); + } + + public function tearDown(): void + { + File::delete($this->dir); + parent::tearDown(); + } + + #[Test] + public function it_references_the_csrf_and_nocache_scripts_instead_of_inlining_them() + { + $this->withFakeViews(); + $this->viewShouldReturnRaw('layout', '