Search code examples
htmldjangonginxweb-optimization

Static file versioning with Django


I am setting far-future expires headers for my CSS/Javascript so that the browsers don't ever ask for the files again once they get cached. I also have a simple versioning mechanism so that if the files change, the clients will know.

Basically I have a template tag and I do something like

<script type="text/javascript" src="{{ MEDIA_URL }}{% versioned "javascript/c/c.js" %}"></script>

which will become

<script type="text/javascript" src="http://x.com/media/javascript/c/c.min.js?123456"></script>.

The template tag opens a file javascript/c/c.js.v where it finds the version number and appends it to the query string. The version is generated by a shell script (run manually for now, will probably add pre-commit hook) which checks whether the file has changed (using git diff).

This is all working fine, EXCEPT:

I want to implement the same kind of versioning for images as well. But images can be referenced from CSS - which is a static file (served by nginx) - so no template tag there.

What is a better approach for file versioning?

Alternatively, I am thinking about replacing the template tag with a middleware which changes all links before returning the response. That is better than the template tag, which can be mistakenly omitted. But still doesn't solve the issue of images referenced from CSS.

Also, I'm aware that having the version as part of the query string might cause trouble with certain proxies not caching the file - so I consider making the version part of the filename - for example javascript/c/c.123456.js.

Note: It looks like there is no way to solve this issue using Django (obviously - since I don't even serve the CSS through Django). But there has to be a solution, perhaps involving some nginx tricks.


Solution

  • Will add another step to my pre-commit script to replace all direct links with links to versioned files in the minimized CSS.

    Seems there is no better way to do it. If you think of any, let me know and I'll consider marking that one as accepted answer.

    Thanks for your comments!