bigywater.tech
Django · 132

静态文件生产部署

开发时静态文件「自己就能用」,上线后就不行了。这篇用真实的 gunicorn 把整个链条走一遍:谁提供文件、collectstatic 做了什么、WhiteNoise 加了什么、用了 Manifest 存储后忘了收集会怎样。

404
DEBUG=False 时 Django 不提供 /static/
132 个文件
collectstatic 的复制数量(含 admin 的静态文件)
忘了 collectstatic
Manifest 存储下 {% static %} 抛 ValueError,页面 500

Django 自己不提供

实测 · 本机执行输出
  GET /static/app.css → 404

collectstatic

实测 · 本机执行输出
  输出最后一行: 132 static files copied to STATIC_ROOT
  STATIC_ROOT 里的文件数: 132  其中来自自己的 static/: ['app.css', 'img.png']  子目录: ['admin']
  不改文件再运行一次: 0 static files copied to STATIC_ROOT

collectstatic 只是把各处的静态文件收集到 STATIC_ROOT,第二次运行只复制有变化的文件。

需要有人来提供

实测 · 本机执行输出
  collectstatic 之后没有中间件   → 404
  加 WhiteNoiseMiddleware        → 200  Content-Length 2837  Cache-Control: max-age=60, public  Last-Modified 有: True

可以是 nginx、CDN,也可以是 WhiteNoise(这里用的方案)。我机器上没有 nginx,所以没有测 nginx 的配置。

Manifest 存储

实测 · 本机执行输出
  没有 collectstatic,GET /page/ → 500 (模板渲染抛异常)
  同样的模板在脚本里渲染 → ValueError: Missing staticfiles manifest entry for 'app.css'
  collectstatic 之后,GET /page/ → 200 <link href="/static/app.1fd618bb1a9a.css">
  GET /static/app.1fd618bb1a9a.css → 200  Cache-Control: max-age=315360000, public, immutable
  CSS 里的 url() 被改写成: img.ca4e399d4a2a.png

性能

实测 · 本机执行输出
  WhiteNoise /static/app.css  0.457 ms
  FileResponse 视图 /dyn/      0.409 ms

别指望 WhiteNoise 比 Django 视图快很多;它的价值是正确的缓存头、压缩与不用改代码。这里只测了单个小文件的串行请求。

分步演示

静态文件上线
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。gunicorn 单 worker;WhiteNoise 6.12.0;一个自己写的 app.css(约 2.8 KB)与 admin 的静态文件
    • 没有验证:nginx / CDN 的配置、WhiteNoise 的压缩文件(gzip / brotli)与 Content-Encoding、大文件、并发下的吞吐、STATIC_URL 带域名(CDN)时的写法、容器里 collectstatic 放在构建阶段还是启动阶段
    京ICP备2026067502号-1京公网安备11010502063487号