Skip to content

Commit

Permalink
[5.x] Move nocache js back to end of body but make configurable (#10898)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonvarga authored Oct 3, 2024
1 parent 7de9f95 commit b3ce9e6
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
2 changes: 2 additions & 0 deletions config/static_caching.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@

'nocache' => 'cache',

'nocache_js_position' => 'body',

/*
|--------------------------------------------------------------------------
| Replacers
Expand Down
39 changes: 30 additions & 9 deletions src/StaticCaching/Replacers/NoCacheReplacer.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,40 @@ private function modifyFullMeasureResponse(Response $response)
$contents = $response->getContent();

if ($cacher->shouldOutputJs()) {
$insertBefore = collect([
Str::position($contents, '<link'),
Str::position($contents, '<script'),
Str::position($contents, '</head>'),
])->filter()->min();

$js = "<script type=\"text/javascript\">{$cacher->getNocacheJs()}</script>";

$contents = Str::substrReplace($contents, $js, $insertBefore, 0);
$contents = match ($pos = $this->insertPosition()) {
'head' => $this->insertJsInHead($contents, $cacher),
'body' => $this->insertJsInBody($contents, $cacher),
default => throw new \Exception('Invalid nocache js insert position ['.$pos.']'),
};
}

$contents = str_replace('NOCACHE_PLACEHOLDER', $cacher->getNocachePlaceholder(), $contents);

$response->setContent($contents);
}

private function insertPosition()
{
return config('statamic.static_caching.nocache_js_position', 'body');
}

private function insertJsInHead($contents, $cacher)
{
$insertBefore = collect([
Str::position($contents, '<link'),
Str::position($contents, '<script'),
Str::position($contents, '</head>'),
])->filter()->min();

$js = "<script type=\"text/javascript\">{$cacher->getNocacheJs()}</script>";

return Str::substrReplace($contents, $js, $insertBefore, 0);
}

private function insertJsInBody($contents, $cacher)
{
$js = $cacher->getNocacheJs();

return str_replace('</body>', '<script type="text/javascript">'.$js.'</script></body>', $contents);
}
}
14 changes: 7 additions & 7 deletions tests/StaticCaching/FullMeasureStaticCachingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function index()
})::register();

$this->withFakeViews();
$this->viewShouldReturnRaw('layout', '<html><head></head><body>{{ template_content }}</body></html>');
$this->viewShouldReturnRaw('layout', '<html><body>{{ template_content }}</body></html>');
$this->viewShouldReturnRaw('default', '{{ example_count }} {{ nocache }}{{ example_count }}{{ /nocache }}');

$this->createPage('about');
Expand All @@ -75,14 +75,14 @@ public function index()
$region = app(Session::class)->regions()->first();

// Initial response should be dynamic and not contain javascript.
$this->assertEquals('<html><head></head><body>1 2</body></html>', $response->getContent());
$this->assertEquals('<html><body>1 2</body></html>', $response->getContent());

// The cached response should have the nocache placeholder, and the javascript.
$this->assertTrue(file_exists($this->dir.'/about_.html'));
$this->assertEquals(vsprintf('<html><head>%s</head><body>1 <span class="nocache" data-nocache="%s">%s</span></body></html>', [
'<script type="text/javascript">js here</script>',
$this->assertEquals(vsprintf('<html><body>1 <span class="nocache" data-nocache="%s">%s</span>%s</body></html>', [
$region->key(),
'<svg>Loading...</svg>',
'<script type="text/javascript">js here</script>',
]), file_get_contents($this->dir.'/about_.html'));
}

Expand Down Expand Up @@ -135,7 +135,7 @@ public function index()
public function it_should_add_the_javascript_if_there_is_a_csrf_token()
{
$this->withFakeViews();
$this->viewShouldReturnRaw('layout', '<html><head></head><body>{{ template_content }}</body></html>');
$this->viewShouldReturnRaw('layout', '<html><body>{{ template_content }}</body></html>');
$this->viewShouldReturnRaw('default', '{{ csrf_token }}');

$this->createPage('about');
Expand All @@ -149,11 +149,11 @@ public function it_should_add_the_javascript_if_there_is_a_csrf_token()
->assertOk();

// Initial response should be dynamic and not contain javascript.
$this->assertEquals('<html><head></head><body>'.csrf_token().'</body></html>', $response->getContent());
$this->assertEquals('<html><body>'.csrf_token().'</body></html>', $response->getContent());

// The cached response should have the token placeholder, and the javascript.
$this->assertTrue(file_exists($this->dir.'/about_.html'));
$this->assertEquals(vsprintf('<html><head>%s</head><body>STATAMIC_CSRF_TOKEN</body></html>', [
$this->assertEquals(vsprintf('<html><body>STATAMIC_CSRF_TOKEN%s</body></html>', [
'<script type="text/javascript">js here</script>',
]), file_get_contents($this->dir.'/about_.html'));
}
Expand Down

0 comments on commit b3ce9e6

Please sign in to comment.