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:
@@ -271,5 +271,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/admin-user-detail.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/admin-user-detail.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -353,5 +353,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/admin-user-edit.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/admin-user-edit.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -283,5 +283,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/admin-users.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/admin-users.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -210,6 +210,6 @@
|
||||
</script>
|
||||
|
||||
<!-- 6. Login Logic -->
|
||||
<script defer src="{{ url_for('core_static', path='admin/js/login.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'core_static', path='admin/js/login.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -483,5 +483,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchant-detail.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchant-detail.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -490,5 +490,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchant-edit.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchant-edit.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -281,5 +281,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchant-user-detail.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchant-user-detail.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -247,5 +247,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchant-user-edit.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchant-user-edit.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -250,5 +250,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchant-users.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchant-users.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -257,5 +257,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/merchants.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/merchants.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -233,5 +233,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platform-create.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platform-create.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -221,5 +221,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platform-detail.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platform-detail.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -342,5 +342,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platform-edit.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platform-edit.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -223,5 +223,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platform-menu-config.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platform-menu-config.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -303,5 +303,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platform-modules.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platform-modules.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -123,5 +123,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/platforms.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/platforms.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
<script defer src="{{ url_for('static', path='shared/js/utils.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', path='shared/js/api-client.js') }}"></script>
|
||||
<script defer src="{{ url_for('static', path='shared/js/icons.js') }}"></script>
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/select-platform.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/select-platform.js') }}"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.13.3/dist/cdn.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -279,5 +279,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/store-create.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/store-create.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -661,5 +661,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/store-detail.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/store-detail.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -477,5 +477,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/store-edit.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/store-edit.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -267,5 +267,5 @@
|
||||
<script>
|
||||
window._adminStoreRolesConfig = { isSuperAdmin: {{ is_super_admin | tojson }} };
|
||||
</script>
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/store-roles.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/store-roles.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -248,5 +248,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/stores.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/stores.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -191,5 +191,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='admin/js/user-create.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='admin/js/user-create.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -211,6 +211,6 @@
|
||||
</script>
|
||||
|
||||
<!-- 6. Merchant Login Logic -->
|
||||
<script defer src="{{ url_for('core_static', path='merchant/js/login.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'core_static', path='merchant/js/login.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -534,5 +534,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='merchant/js/merchant-team.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='merchant/js/merchant-team.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
</script>
|
||||
|
||||
<!-- 7. Store Login Logic -->
|
||||
<script defer src="{{ url_for('tenancy_static', path='store/js/login.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='store/js/login.js') }}"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -202,5 +202,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='store/js/profile.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='store/js/profile.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -163,5 +163,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='store/js/roles.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='store/js/roles.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1328,5 +1328,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='store/js/settings.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='store/js/settings.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -299,5 +299,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer src="{{ url_for('tenancy_static', path='store/js/team.js') }}"></script>
|
||||
<script defer src="{{ static_v(request, 'tenancy_static', path='store/js/team.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user