From 51d6e220ee58f2474fc84d7cf741390a15a331bc Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 29 Sep 2026 11:32:35 +0800 Subject: [PATCH] =?UTF-8?q?perf(core):=20=E6=9E=84=E5=BB=BA=E4=BA=A7?= =?UTF-8?q?=E7=89=A9=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90=E6=94=B9=2072h=20?= =?UTF-8?q?=E5=BC=BA=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _serve_file 识别 Vite 内容 hash 文件名(-.,hash 段须含大写或数字) - hash 产物: public, max-age=259200, immutable(72h,路径随版本变化不影响新版本生效) - 非 hash 的传统资源保持 1h/24h,index.html 仍 no-cache --- gvsds/apps/core/views.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gvsds/apps/core/views.py b/gvsds/apps/core/views.py index 53558e2d..9ab37e6f 100644 --- a/gvsds/apps/core/views.py +++ b/gvsds/apps/core/views.py @@ -1,4 +1,5 @@ import os +import re import mimetypes from pathlib import Path from django.http import HttpResponse, Http404, JsonResponse, HttpResponseRedirect @@ -8,6 +9,14 @@ from gvsds.template_engine import render_template TEMPLATE_DIR = Path(settings.BASE_DIR) / "TempLate" +#: 构建产物(Vite 输出 -.)的强缓存时长:72 小时 +#: 依据:文件名内含内容 hash,内容与名字一一对应;新版本会换新文件名, +#: 因此不会出现「改了代码但客户端还是旧文件」的问题(index.html 仍为 no-cache)。 +HASHED_ASSET_MAX_AGE = 60 * 60 * 72 +#: 识别构建产物名:-<8 位以上 hash>.,且 hash 段须含大写字母或数字 +#: (避免误伤 gvs-design-system.css 这类全小写连字符的传统文件名) +HASHED_ASSET_RE = re.compile(r'-(?=[A-Za-z0-9_-]*[A-Z0-9])[A-Za-z0-9_-]{8,}\.[A-Za-z0-9]+$') + MIME_TYPES = { '.js': 'application/javascript', '.mjs': 'application/javascript', @@ -152,7 +161,12 @@ def _serve_file(full_path, subdomain=None): with open(full_path, 'rb') as f: response = HttpResponse(f.read(), content_type=content_type) - if ext in ('.css', '.js', '.mjs', '.json', '.xml', '.txt', '.svg'): + if HASHED_ASSET_RE.search(full_path.name): + # Vite 构建产物(如 index-C_-1ws_N.js / style-BWB-O5Ko.css): + # 文件名含内容 hash,路径随版本变化,可长期强缓存 + immutable 免协商 + response['Cache-Control'] = f'public, max-age={HASHED_ASSET_MAX_AGE}, immutable' + elif ext in ('.css', '.js', '.mjs', '.json', '.xml', '.txt', '.svg'): + # 非 hash 命名的传统静态资源(legacy 站点),改动后需较快生效 response['Cache-Control'] = 'public, max-age=3600' elif ext in ('.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.woff', '.woff2', '.ttf', '.eot', '.mp4'): response['Cache-Control'] = 'public, max-age=86400'