Skip to content

Commit 321ea6e

Browse files
Merge pull request #41 from niteeshkanna-sh/claude/stoic-rubin-fnglq7
Stop the panel's own scripts being cached for a year
2 parents b1f110e + 88697bd commit 321ea6e

5 files changed

Lines changed: 62 additions & 7 deletions

File tree

‎admin/.htaccess‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,29 @@
88
# its contents, which is how the layout of a panel gets mapped.
99
Options -Indexes
1010

11+
# Undo the document root's caching rule for this folder.
12+
#
13+
# The site's build assets carry a content hash in the filename, so a changed
14+
# file is a changed URL and the root .htaccess caches every .js and .css for a
15+
# year as immutable. Correct for those. Fatal for these: admin.js, admin.css,
16+
# api.js and car-data.js have fixed names, so a browser that has them once
17+
# would never ask again -- and every change to the panel would reach nobody who
18+
# had ever used it, with no error and nothing to notice.
19+
#
20+
# Revalidated on each load instead. It costs one conditional request per file
21+
# and it is the difference between shipping a change and appearing to.
22+
<IfModule mod_expires.c>
23+
<FilesMatch "\.(js|css)$">
24+
ExpiresActive On
25+
ExpiresDefault "access plus 0 seconds"
26+
</FilesMatch>
27+
</IfModule>
28+
<IfModule mod_headers.c>
29+
<FilesMatch "\.(js|css)$">
30+
Header set Cache-Control "no-cache, must-revalidate"
31+
</FilesMatch>
32+
</IfModule>
33+
1134
<IfModule mod_authz_core.c>
1235
# config.php holds the database password. PHP executes it rather than
1336
# printing it, so this changes nothing while PHP is healthy -- it matters

‎admin/content.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
declare(strict_types=1);
33

44
require_once __DIR__ . '/src/csrf.php';
5+
require_once __DIR__ . '/src/assets.php';
56
require_once __DIR__ . '/src/content.php';
67
require_once __DIR__ . '/src/migrate.php';
78
require_once __DIR__ . '/src/audit.php';
@@ -105,7 +106,7 @@ function field_input(string $name, array $spec, mixed $value): void
105106
<title>Website content — NiteSha Cars</title>
106107
<meta name="robots" content="noindex, nofollow" />
107108
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔐</text></svg>" />
108-
<link rel="stylesheet" href="admin.css" />
109+
<link rel="stylesheet" href="<?= asset('admin.css') ?>" />
109110
<style>
110111
.c-wrap { max-width: 56rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
111112
.c-top { display: flex; flex-wrap: wrap; gap: 1rem; align-items: baseline; justify-content: space-between; margin-bottom: 1.25rem; }

‎admin/dashboard.php‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
declare(strict_types=1);
33

44
require_once __DIR__ . '/src/csrf.php';
5+
require_once __DIR__ . '/src/assets.php';
56

67
// Anyone reaching this page must already be signed in; require_login sends
78
// them to the sign-in form otherwise.
@@ -22,7 +23,7 @@
2223
<link rel="preconnect" href="https://fonts.googleapis.com">
2324
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet">
2425
<meta name="csrf-token" content="<?= e(csrf_token()) ?>">
25-
<link rel="stylesheet" href="admin.css" />
26+
<link rel="stylesheet" href="<?= asset('admin.css') ?>" />
2627
</head>
2728
<body>
2829

@@ -751,9 +752,9 @@
751752
</div>
752753
</div>
753754

754-
<script src="api.js"></script>
755-
<script src="car-data.js"></script>
756-
<script src="booking-data.js"></script>
757-
<script src="admin.js"></script>
755+
<script src="<?= asset('api.js') ?>"></script>
756+
<script src="<?= asset('car-data.js') ?>"></script>
757+
<script src="<?= asset('booking-data.js') ?>"></script>
758+
<script src="<?= asset('admin.js') ?>"></script>
758759
</body>
759760
</html>

‎admin/index.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
declare(strict_types=1);
33

44
require_once __DIR__ . '/src/csrf.php';
5+
require_once __DIR__ . '/src/assets.php';
56

67
// Already signed in — go straight through.
78
if (current_user() !== null) {
@@ -44,7 +45,7 @@
4445
<meta name="robots" content="noindex, nofollow">
4546
<link rel="preconnect" href="https://fonts.googleapis.com">
4647
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet">
47-
<link rel="stylesheet" href="admin.css">
48+
<link rel="stylesheet" href="<?= asset('admin.css') ?>">
4849
</head>
4950
<body>
5051

‎admin/src/assets.php‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* URLs for the panel's own stylesheet and scripts.
6+
*
7+
* admin.js and admin.css have fixed names, unlike the site's build output
8+
* which carries a content hash in the filename. The document root caches every
9+
* .js and .css for a year as immutable -- correct for hashed files, fatal for
10+
* these: a browser that loaded the panel once would never fetch them again, so
11+
* a change reached nobody who had ever used it, with no error and nothing to
12+
* notice.
13+
*
14+
* admin/.htaccess now overrides that header, but only for browsers that ask,
15+
* and one already holding the file will not ask until next year. The
16+
* modification time in the query string is what actually breaks that: a
17+
* changed file is a different URL, so the cached copy cannot match.
18+
*
19+
* Its own file rather than http.php, which is the JSON endpoints' plumbing and
20+
* is not loaded by any page that renders HTML. Putting it there defined it
21+
* exactly where it was never called from.
22+
*/
23+
24+
function asset(string $file): string
25+
{
26+
$path = __DIR__ . '/../' . $file;
27+
$stamp = is_file($path) ? (string) filemtime($path) : '0';
28+
return $file . '?v=' . $stamp;
29+
}

0 commit comments

Comments
 (0)