Skip to content

Commit b3ce9e6

Browse files
authored
[5.x] Move nocache js back to end of body but make configurable (#10898)
1 parent 7de9f95 commit b3ce9e6

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

config/static_caching.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125

126126
'nocache' => 'cache',
127127

128+
'nocache_js_position' => 'body',
129+
128130
/*
129131
|--------------------------------------------------------------------------
130132
| Replacers

src/StaticCaching/Replacers/NoCacheReplacer.php

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,40 @@ private function modifyFullMeasureResponse(Response $response)
7979
$contents = $response->getContent();
8080

8181
if ($cacher->shouldOutputJs()) {
82-
$insertBefore = collect([
83-
Str::position($contents, '<link'),
84-
Str::position($contents, '<script'),
85-
Str::position($contents, '</head>'),
86-
])->filter()->min();
87-
88-
$js = "<script type=\"text/javascript\">{$cacher->getNocacheJs()}</script>";
89-
90-
$contents = Str::substrReplace($contents, $js, $insertBefore, 0);
82+
$contents = match ($pos = $this->insertPosition()) {
83+
'head' => $this->insertJsInHead($contents, $cacher),
84+
'body' => $this->insertJsInBody($contents, $cacher),
85+
default => throw new \Exception('Invalid nocache js insert position ['.$pos.']'),
86+
};
9187
}
9288

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

9591
$response->setContent($contents);
9692
}
93+
94+
private function insertPosition()
95+
{
96+
return config('statamic.static_caching.nocache_js_position', 'body');
97+
}
98+
99+
private function insertJsInHead($contents, $cacher)
100+
{
101+
$insertBefore = collect([
102+
Str::position($contents, '<link'),
103+
Str::position($contents, '<script'),
104+
Str::position($contents, '</head>'),
105+
])->filter()->min();
106+
107+
$js = "<script type=\"text/javascript\">{$cacher->getNocacheJs()}</script>";
108+
109+
return Str::substrReplace($contents, $js, $insertBefore, 0);
110+
}
111+
112+
private function insertJsInBody($contents, $cacher)
113+
{
114+
$js = $cacher->getNocacheJs();
115+
116+
return str_replace('</body>', '<script type="text/javascript">'.$js.'</script></body>', $contents);
117+
}
97118
}

tests/StaticCaching/FullMeasureStaticCachingTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function index()
5858
})::register();
5959

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

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

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

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

@@ -135,7 +135,7 @@ public function index()
135135
public function it_should_add_the_javascript_if_there_is_a_csrf_token()
136136
{
137137
$this->withFakeViews();
138-
$this->viewShouldReturnRaw('layout', '<html><head></head><body>{{ template_content }}</body></html>');
138+
$this->viewShouldReturnRaw('layout', '<html><body>{{ template_content }}</body></html>');
139139
$this->viewShouldReturnRaw('default', '{{ csrf_token }}');
140140

141141
$this->createPage('about');
@@ -149,11 +149,11 @@ public function it_should_add_the_javascript_if_there_is_a_csrf_token()
149149
->assertOk();
150150

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

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

0 commit comments

Comments
 (0)