Description
First, thanks for this project and your accompanying blog!
I am using django-whitenoise
with this, which is a derivative of Django's ManifestStaticFilesStorage
storage backend that adds forever-cacheable headers. All worked well except I noticed for some reason my bundle asset (let's call it $STATIC/js/main.js
) was not being served correctly, unlike all other static assets.
In general, in this kind of setup, collectstatic
transforms files by adding a content hash for the file name, for example js/main.js
might be copied to $STATIC_ROOT/js/main.536ce6ddaf7b.js
. The hashes are transparently added by the staticfiles backend, so a URL like {% static 'js/main.js' %}
should automatically be translated to the hashed URL when served/rendered. For some reason, render_bundle
did not do this.
It turns out there are two unrelated behaviors that are at play here:
-
collectstatic
copies both the original resource and its hashed filename to the destination. So bothjs/main.js
andjs/main.536ce6ddaf7b.js
can be served by the application — which in my case masked the fact that the hashed file was never being served (i.e. nothing in the app breaks, it just doesn't get the nice caching features). -
When
django-webpack-loader
is called to render a bundle, it determines the URL in one of two ways, depending on thewebpack-stats.json
metadata for the chunk:- If the chunk has a
publicPath
, return that as the URL exactly. - Otherwise, call
staticfiles_storage.url()
for$BUNDLE_DIR_NAME/$CHUNK
.
- If the chunk has a
Because my original webpack.config.prod.js
had a line like like this:
config.output.publicPath = '/static/js/';
... my calls to render_bundle
would take that first branch & never call staticfiles_storage.url
, returning the "plain" unhashed asset. The fix is simple: remove thepublicPath
config.
In summary: Don't set output.publicPath
in prod unless you know what you're doing; webpack loader will not consult your staticfiles backend if you do.
(PS: I'm guessing this isn't actionable, my apologies if this obvious to more webpack-savvy folks. I'm pretty unfamiliar with webpack/django guts, so I figured I'd splat some notes here for searchability if nothing else, in case another noob trips up like I did. cheers!)