In Sphinx's conf.py
I have:
html_css_files = ['css/custom.css']
html_js_files = ['js/custom.js']
However if I make any change in custom.js
or custom.css
then this change does not reflect to in the user's browser unless http://www.example.com/_static/js/custom.js is forcefully reloaded on the client (similarly for CSS).
How can I force the custom CSS + JS to never cache on the user's browser?
Builds with the below solution in them are now failing with:
Reason: ThemeError("Local asset file paths must not contain query strings: '_static/custom.css?v=12345678'")
According to bug reports this also broke builds with several other large projects like MathJax, NumPy, Gentoo & bokee.
According to a Sphinx contributor, the reason is that Sphinx should now natively handle cache busting via a content checksum, meaning that manual cache busting no longer needs to be done (per the guide below).
Although the config file looks like it only accepts normal string values, it is really just a Python script, so we can import and use functions such as a random number generator.
At the top of conf.py
add this line:
from secrets import token_urlsafe
Change your custom CSS + JS to:
html_css_files = [f'css/custom.css?v={token_urlsafe(8)[:8]}']
html_js_files = [f'js/custom.js?v={token_urlsafe(8)[:8]}']
This will make your custom CSS + JS files load like the vanilla CSS + JS files, with a random 8-character slug at the end - thus disabling caching:
<!-- Sphinx vanilla CSS: -->
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=80d5e7a1" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
<!-- Our custom CSS now has a random slug, like vanilla: -->
<link rel="stylesheet" type="text/css" href="../_static/css/custom.css?v=Rdy7RNCQ" />
<!-- Sphinx vanilla JS: -->
<script src="../_static/jquery.js?v=5d32c60e"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js?v=e91dff3d"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=4825356b"></script>
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
<script src="../_static/copybutton.js?v=f281be69"></script>
<!-- Our custom JS now has a random slug, like vanilla: -->
<script src="../_static/js/custom.js?v=8QronLhw"></script>
Note that if you're running Sphinx in Docker then the ?v=xxxxxxxx
slug will not change unless you run your docker build
with the --no-cache
option.