`get_chunk_url` always uses `publicPath`, prevents cdn host.
nitsujri opened this issue · 3 comments
Problem
Currently if using a custom_domain
on something that extends S3ManifestStaticStorage
for a separate cdn for assets like cdn.example.com
and in the webpack configuration defines uses publicPath
, the custom_domain
never gets loaded:
https://github.com/django-webpack/django-webpack-loader/blob/master/webpack_loader/loaders.py#L81
Bad Solution
In Webpack, for any deployed env (like prod), one could set output: { publicPath: '', },
in the webpack config. This prevents publicPath being created for any asset in the manifest.json.
We tried this but it forces img, font assets to be inside the css folder due to the way references are built without a publicPath.
Best Work Around
Currently, we monkey patch get_chunk_url
(works perfectly well for us):
import os
from django.contrib.staticfiles.storage import staticfiles_storage
from webpack_loader.loader import WebpackLoader
def get_chunk_url(self, chunk_file):
# Removed by Monkey Patch
# public_path = chunk_file.get('publicPath')
# if public_path:
# return public_path
# Use os.path.normpath for Windows paths
relpath = os.path.normpath(
os.path.join(self.config["BUNDLE_DIR_NAME"], chunk_file["name"])
)
return staticfiles_storage.url(relpath)
WebpackLoader.get_chunk_url = get_chunk_url
Solution
Honestly, I don't know what a good solution is here? Possible:
- Carry a variable
render_bundle
? Seems very distant. settings.WEBPACK_USE_PUBLICPATH_FROM_CHUNK_FILE
- feels like the best of poisons?
For the current 2.0.1 version, you need to repeat your STATIC_URL in your webpack.config.js
. Like:
const path = require("path");
const STATIC_URL = process.env.STATIC_URL || '/';
module.exports = {
// ...
output: {
path: path.resolve("./frontend/webpack_bundles/"),
publicPath: `${STATIC_URL}webpack_bundles/`,
filename: "[name]-[chunkhash].js",
},
};
To build and collect static during your production deploys, run something like:
NODE_ENV=production STATIC_URL="your-custom-cdn-domain.com/" webpack --progress --bail --mode=production
python manage.py collectstatic --noinput
If you already have staticfiles properly configured in your Django-side, there's a way to indirectly pass the STATIC_URL to Webpack assets at runtime, which is publicPath: "auto"
. See: #350 (comment)
Closing this for now, let me know if you can't solve the issue and I will re-open it.
Thanks for the reply and appreciate the depth. I also recognize that the recommendation probably works for others well.
For us though, the suggested solution isnt ideal as the build is agnostic to the deployment environment. One Docker file builds as single container that can be deployed for production, uat and/or staging. The build env doesn't know where it will end up and I argue it shouldn't. The builder simply builds "for some production-like destination".
Hence we like Django writing the asset's URL.
@nitsujri makes sense, but I guess publicPath: "auto"
will work for your case. Please let me know if #350 (comment) works for you or not.