我为我的CSS / Javascript设置了远期过期头文件,以便浏览器在得到caching后再也不要求文件。 我也有一个简单的版本机制,所以如果文件改变,客户端将知道。
基本上我有一个模板标签,我做了类似的事情
<script type="text/javascript" src="{{ MEDIA_URL }}{% versioned "javascript/c/c.js" %}"></script>
这将成为
<script type="text/javascript" src="http://x.com/media/javascript/c/c.min.js?123456"></script>
。
模板标记将打开一个文件javascript/c/c.js.v
,在该文件中查找版本号并将其附加到查询string中。 该版本是由一个shell脚本生成(现在手动运行,可能会添加预先提交钩子),检查文件是否已经改变(使用git diff
)。
这一切都工作正常,除了:
我想为图像实现相同types的版本。 但是图像可以从CSS引用 – 这是一个静态文件(由nginx提供) – 所以没有模板标签。
什么是更好的文件版本的方法?
或者,我正在考虑用返回响应之前更改所有链接的中间件replace模板标记。 这比模板标签要好,可能会被误删。 但仍然不能解决从CSS引用的图像问题。
此外,我知道有版本作为查询string的一部分可能会导致某些代理不caching文件的麻烦 – 所以我考虑使版本的一部分的文件名 – 例如javascript/c/c.123456.js
。
注意:看起来像使用Django没有办法解决这个问题(显然 – 因为我甚至没有通过Django服务于CSS)。 但是必须有一个解决scheme,可能涉及到一些nginx技巧。
样式表资产
对于你的样式表引用的资产,使用Sass&Compass更好。 Compass有一个mixin,它会自动将版本查询参数添加到样式表中引用的静态资产的末尾。 版本号仅在重建样式表时发生变化(在本地开发时,这对于compass watch
是微不足道的)。
模板资产
对于其他文件,我实际上会使用某种类型的post-pull钩子来重写一个python模块,其唯一目的是包含当前版本。
/var/www/aweso.me/ ./files/ ./private-files/ ./static/ ./project/ ./manage.py ./fabfile.py ./.gitignore ./base/ ./__init__.py ./wsgi.py ./settings/ ./__init__.py ./modules ./__init__.py ./users.py ./email.py ./beta.py ./redis.py ./haystack.py ./version.py ./default.py ./local.py ./live.py
你的帖子拉钩将创建:
/var/www/aweso.me/project/base/settings/version.py
其中将包含最新(或以前)的git提交哈希:
__version__ = "0763j34bf"
然后在你的settings.live
使用一个简单from .version import __version__ as ApplicationVersion
,你的模板标签可以简单地使用from settings import ApplicationVersion
来将那个查询参数写成缓存。
我们使用这个简单的模板标签来生成基于文件修改时间的版本号:
import os import posixpath import stat import urllib from django import template from django.conf import settings from django.contrib.staticfiles import finders register = template.Library() @register.simple_tag def staticfile(path): normalized_path = posixpath.normpath(urllib.unquote(path)).lstrip('/') absolute_path = finders.find(normalized_path) if not absolute_path and getattr(settings, 'STATIC_ROOT', None): absolute_path = os.path.join(settings.STATIC_ROOT, path) if absolute_path: return '%s%s?v=%s' % (settings.STATIC_URL, path, os.stat(absolute_path)[stat.ST_MTIME]) return path
对于1.3之前的Django,这个标签的版本更简单:
@register.simple_tag def staticfile(path): file_path = os.path.join(settings.MEDIA_ROOT, path) url = '%s%s?v=%s' % (settings.MEDIA_URL, path, os.stat(file_path)[stat.ST_MTIME]) return url
用法:
<link rel="stylesheet" href="{% staticfile "css/style.css" %}" type="text/css" media="screen" />
将我的预先提交脚本添加另一个步骤,以最小化的CSS替换所有直接链接到版本化文件的链接。
似乎没有更好的方法来做到这一点。 如果你想到任何问题,请告诉我,我会考虑将其标记为已接受的答案。
感谢您的意见!
我认为一个简单的解决方案可能是:
这也可以帮助: http : //www.fanstatic.org/