Django's 'static' tag generates urls using STATIC_URL, which results in something like '/static/myapp/js/bundle.js' Mean while, webpack-dev-server is serving bundles from the url 'localhost:3000'
My question is how do I get Django 'static' template tag to generate a different url ( which points to webpack dev server) for js bundles. Of course I can hardcode it in the template, but that would not be a good solution.
Below is my project configuration
webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const BundleTracker = require('webpack-bundle-tracker')
module.exports = {
mode: 'development',
context: path.dirname(path.resolve(__dirname)),
entry: {
index: './typescript_src/index.ts',
},
output: {
path: path.resolve('./myproject/assets/myapp/bundles/'),
filename: "[name]-[hash].js"
},
resolve: {
extensions: ['.ts', '.js' ]
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new BundleTracker({filename: './myproject/webpack-stats.json'})
],
devServer: {
port: 3000,
publicPath: '/myapp/bundles/',
// hot: true,
headers: {
"Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
}
}
}
settings.py
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'BUNDLE_DIR_NAME': 'myapp/bundles/', # must end with slash
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'TIMEOUT': None,
'IGNORE': [r'.+\.hot-update.js', r'.+\.map']
}
}
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'assets'),
)
Initially I decided webpack should serve other static files as well during development
webpack.config.js
devServer: {
port: 3000,
publicPath: '/myapp/bundles/',
contentBase: path.resolve('./myproject/assets')
// hot: true,
headers: {
"Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
}
settings.py
# in development mode serve from wepack dev server
if DEBUG:
STATIC_URL = 'http://localhost:3000/'
else:
STATIC_URL = '/static/'
But I later realized I have to serve static files of other apps (admin, tinymce, ...), which is impossible for webpack Dev server to reach
The problem here is that the url generated by 'render_bundle' tag of django-webpack-loader (/static/myapp/bundles/bundle-name.js) will result in a Http 404 because webpack-dev-server keeps the generated bundle in memory and not on disk
Also if I set
STATIC_URL = localhost:3000
and configure webpack-dev-server to serve other static files of my app, static files of other apps won't be served
The webpack-dev-server will serve the files in the current directory, unless you configure a specific content base. Using this config webpack-dev-server will serve the static files in your public folder. It'll watch your source files for changes and when changes are made the bundle will be recompiled.
Use webpack to generate your static bundles without django's staticfiles or opaque wrappers. Django webpack loader consumes the output generated by webpack-bundle-tracker and lets you use the generated bundles in django.
The Result Either method will start a server instance and begin listening for connections from localhost on port 8080 . webpack-dev-server is configured by default to support live-reload of files as you edit your assets while the server is running.
Let's analyze the issue:
We have 2 servers and we want to route requests to one or the other based on the path requested:
"/static/webpackbundles/** ==> webpack dev server
other paths ==> django dev server
This is exactly the job of a proxy server, it can be achieved with a third server (haproxy, nginx ...), but that might seem like an overkill, especially if we know that webpack dev server
can be used as a proxy! (https://webpack.js.org/configuration/dev-server/#devserverproxy)
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: '/path/to/django_project/django_project/static/webpackbundles',
publicPath: '/static/webpackbundles/',
},
devServer: {
contentBase: '/path/to/django_project/django_project/static/webpackbundles',
hot: true,
proxy: {
'!/static/webpackbundles/**': {
target: 'http://localhost:8000', // points to django dev server
changeOrigin: true,
},
},
},
};
In your django template:
<script type="text/javascript" src="{% static 'webpackbundles/main.js' %}"></script>
Now access your django app/site using webpack dev server
address:
ex: http://localhost:8081
With this simple config you'll have browser auto refresh and hot module replacement. You will not need to change anything in django, also no need for django-webpack-loader
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With