feat(static-assets): cache-bust JS/CSS via ?v=<commit-sha>, immutable in prod
All checks were successful
All checks were successful
Adds a `static_v(request, name, path=...)` Jinja helper that appends
?v=<commit-sha> from app.core.build_info, plus a CachedStaticFiles
subclass that serves Cache-Control: public, max-age=31536000, immutable
in production and no-cache in development. Browsers refetch JS/CSS
automatically on every deploy without the user having to hard-reload.
- New: app/core/static_files.py (CachedStaticFiles)
- Updated: app/templates_config.py (static_v helper)
- Updated: main.py (use CachedStaticFiles for *_static mounts)
- Codemod: 143 url_for('*_static', path='*.js'|'*.css') → static_v(...)
across 123 templates. Images/fonts/JSON locales intentionally
unchanged (out of scope).
- Arch rule: FE-024 (warning) flags raw url_for on JS/CSS to prevent
drift. Note: FE-008 was already taken by the number_stepper rule.
- docs/proposals/static-asset-cache-busting.md marked Done.
Closes plan from docs/proposals/static-asset-cache-busting.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -936,6 +936,33 @@ frontend_component_rules:
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/trust-badges.html' import"
|
||||
|
||||
- id: "FE-024"
|
||||
name: "Use static_v() for JS/CSS, not raw url_for()"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Static .js and .css URLs must use the cache-busting `static_v()` helper
|
||||
so browsers refetch automatically after each deploy. The helper appends
|
||||
`?v=<commit-sha>` from app.core.build_info — same SHA across one deploy,
|
||||
flips on the next.
|
||||
|
||||
WRONG (browser keeps cached file after deploy):
|
||||
<script src="{{ url_for('foo_static', path='admin/js/app.js') }}"></script>
|
||||
<link href="{{ url_for('foo_static', path='admin/css/site.css') }}" rel="stylesheet">
|
||||
|
||||
RIGHT:
|
||||
<script src="{{ static_v(request, 'foo_static', path='admin/js/app.js') }}"></script>
|
||||
<link href="{{ static_v(request, 'foo_static', path='admin/css/site.css') }}" rel="stylesheet">
|
||||
|
||||
Images, fonts, and JSON locale files are intentionally out of scope —
|
||||
keep using `url_for()` for those.
|
||||
pattern:
|
||||
file_pattern: "app/**/templates/**/*.html"
|
||||
anti_patterns:
|
||||
- "url_for\\(\\s*['\"]\\w+_static['\"]\\s*,\\s*path=['\"][^'\"]+\\.(?:js|css)['\"]"
|
||||
exceptions:
|
||||
- "base.html"
|
||||
- "partials/"
|
||||
|
||||
# ============================================================================
|
||||
# FRONTEND STYLING RULES
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user