Skip to content

Commit 6f0a94c

Browse files
committed
Clarify usage of BUNDLE_DIR_NAME and STATICFILES_DIRS in README
1 parent 7abad4e commit 6f0a94c

File tree

12 files changed

+262
-212
lines changed

12 files changed

+262
-212
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ examples/**/ve/
7171
examples/**/venv/
7272
examples/**/node_modules/
7373
examples/**/assets/bundles/
74+
examples/**/assets/webpack_bundles/
7475
examples/**/webpack-stats.json
7576

7677
tests/ve/
@@ -79,6 +80,7 @@ tests/venv/
7980
tests/venv3/
8081
tests/node_modules/
8182
tests/assets/bundles/
83+
tests/assets/webpack_bundles/
8284
tests/assets/django_webpack_loader_bundles/
8385
tests/webpack-stats.json
8486
tests/webpack-stats-app2.json

README.md

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ module.exports = {
5252
context: __dirname,
5353
entry: "./assets/js/index",
5454
output: {
55-
path: path.resolve(__dirname, "assets/bundles/"),
55+
path: path.resolve(__dirname, "assets/webpack_bundles/"),
5656
filename: "[name]-[contenthash].js",
5757
},
5858
plugins: [
@@ -80,8 +80,13 @@ INSTALLED_APPS = (
8080
Below is the recommended setup for the Django settings file when using `django-webpack-loader`.
8181

8282
```python
83+
STATICFILES_DIRS = (
84+
os.path.join(BASE_DIR, 'assets'),
85+
)
86+
8387
WEBPACK_LOADER = {
8488
'DEFAULT': {
89+
'BUNDLE_DIR_NAME': 'webpack_bundles/',
8590
'CACHE': not DEBUG,
8691
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
8792
'POLL_INTERVAL': 0.1,
@@ -90,7 +95,9 @@ WEBPACK_LOADER = {
9095
}
9196
```
9297

93-
For that setup, we're using the `DEBUG` variable provided by Django. Since in a production environment (`DEBUG = False`) the assets files won't constantly change, we can safely cache the results (`CACHE=True`) and optimize our flow, as `django-webpack-loader` will read the stats file only once and store the assets files paths in memory. From that point onwards, it will use these stored paths as the source of truth. If `CACHE=False`, we'll always read the stats file to get the assets paths.
98+
Note that you must set the path where you're keeping your static assets and Webpack bundles in `STATICFILES_DIRS`.
99+
100+
For that setup, we're using the `DEBUG` variable provided by Django. Since in a production environment (`DEBUG = False`) the assets files won't constantly change, we can safely cache the results (`CACHE=True`) and optimize our flow, as `django-webpack-loader` will read the stats file only once and store the assets paths in memory. If `CACHE=False`, we'll always read the stats file to get the assets paths.
94101

95102
The `STATS_FILE` parameter represents the output file produced by `webpack-bundle-tracker`. Since in the Webpack configuration file we've named it `webpack-stats.json` and stored it on the project root, we must replicate that setting on the backend side.
96103

@@ -159,17 +166,51 @@ WEBPACK_LOADER['DEFAULT']['LOADER_CLASS'] = 'webpack_loader.loaders.FakeWebpackL
159166

160167
## Using in Production
161168

162-
The recommended apporach is to have a production pipeline that generates the frontend bundle along with the stats file during the **deployment phase**. We recommend keeping the generated bundles and the stats file outside the version control. In other words, add `webpack-stats.json` and `assets/bundles/` to your `.gitignore`.
169+
The recommended apporach is to have a production pipeline that generates the frontend bundle along with the stats file during the **deployment phase**. We recommend keeping the generated bundles and the stats file outside the version control. In other words, add `webpack-stats.json` and `assets/webpack_bundles/` to your `.gitignore`.
163170

164-
A simple production deployment can use Django's own `collectstatic`. If Django is serving your static files, remember you must configure the `STATICFILES_DIRS`:
171+
Assuming static files is properly configured using Django built-ins or something like [django-storages](https://django-storages.readthedocs.io/), a simple production deployment can use Django's own `collectstatic`. Remember the Django settings values of `STATICFILES_DIRS`, `BUNDLE_DIR_NAME`, `STATS_FILE`, and Webpack's `output.path` must all be compatible:
172+
173+
```javascript
174+
// webpack.config.js
175+
module.exports = {
176+
// ...
177+
context: __dirname,
178+
output: {
179+
// Emit bundle files at "assets/webpack_bundles/":
180+
path: path.resolve(__dirname, "assets/webpack_bundles/"),
181+
filename: "[name]-[contenthash].js",
182+
},
183+
plugins: [
184+
// Emit 'webpack-stats.json' in project root for Django to find it:
185+
new BundleTracker({ path: __dirname, filename: "webpack-stats.json" }),
186+
],
187+
};
188+
```
165189

166190
```python
191+
# app/settings.py
192+
193+
BASE_DIR = ... # set to project root
194+
167195
STATICFILES_DIRS = (
196+
# make Django collect all "assets/" and "assets/webpack_bundles"
197+
# to be served at "my-static-url.com/asset-name.png"
198+
# and "my-static-url.com/webpack_bundles/main.js"
168199
os.path.join(BASE_DIR, 'assets'),
169200
)
201+
202+
WEBPACK_LOADER = {
203+
'DEFAULT': {
204+
# Bundle directory, like in "my-static-url.com/webpack_bundles/main.js":
205+
'BUNDLE_DIR_NAME': 'webpack_bundles/',
206+
# Absolute path to where 'webpack-stats.json' is in Django project root:
207+
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
208+
# ...
209+
}
210+
}
170211
```
171212

172-
With `collectstatic` properly configured, you must first run your Webpack build in production-mode, then call `collectstatic`. For example, your deployment script should do something like this before (re)starting the Django webserver:
213+
In your deployment script, you must first run your Webpack build in production-mode, before calling `collectstatic`:
173214

174215
```
175216
NODE_ENV=production webpack --progress --bail --mode=production
@@ -192,6 +233,10 @@ However, production usage for this package is **fairly flexible**, as the entire
192233

193234
In case you wish to use [Dynamic Imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports), please check out [this example](https://github.com/django-webpack/django-webpack-loader/tree/master/examples/dynamic-imports), in particular how [webpack.config.js](https://github.com/django-webpack/django-webpack-loader/blob/master/examples/dynamic-imports/webpack.config.js) is configured. The key is to set the `publicPath`.
194235

236+
### Extra options for `webpack-bundle-tracker`
237+
238+
Check `webpack-bundle-tracker` [README](https://github.com/django-webpack/webpack-bundle-tracker) for all supported options, such as relative paths, integrity hashes, timestamp logging, etc.
239+
195240
### Extra `WEBPACK_LOADER` settings in Django
196241

197242
Set those extra settings inside like this:
@@ -205,7 +250,7 @@ WEBPACK_LOADER = {
205250

206251
- `TIMEOUT` is the number of seconds webpack_loader should wait for Webpack to finish compiling before raising an exception. `0`, `None` or leaving the value out of settings disables timeouts
207252

208-
- `INTEGRITY` is flag enabling [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) on rendered `<script>` and `<link>` tags. Integrity hash is get from stats file and configuration on side of `BundleTracker`, where configuration option `integrity: true` is required.
253+
- `INTEGRITY` is flag enabling [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) on rendered `<script>` and `<link>` tags. Integrity hash is get from stats file and configuration on side of `BundleTracker`, where [configuration option](https://github.com/django-webpack/webpack-bundle-tracker#options) `integrity: true` is required.
209254

210255
- `LOADER_CLASS` is the fully qualified name of a python class as a string that holds the custom Webpack loader. This is where behavior can be customized as to how the stats file is loaded. Examples include loading the stats file from a database, cache, external URL, etc. For convenience, `webpack_loader.loaders.WebpackLoader` can be extended. The `load_assets` method is likely where custom behavior will be added. This should return the stats file as an object.
211256

@@ -221,8 +266,6 @@ class ExternalWebpackLoader(WebpackLoader):
221266
return requests.get(url).json()
222267
```
223268

224-
- `WEBPACK_CHUNK_URL_USE_PUBLIC_PATH` (Default: `True`) is a flag that enables using the Webpack's [publicPath](https://webpack.js.org/guides/public-path/) config as the chunk URL. Setting this to false may be useful if you are using both publicPath and a S3Storage with a custom domain.
225-
226269
- `SKIP_COMMON_CHUNKS` (Default: `False`) is a flag which prevents already generated chunks from being included again in the same page. This should only happen if you use more than one entrypoint per Django template (multiple `render_bundle` calls). By enabling this, you can get the same default behavior of the [HtmlWebpackPlugin](https://webpack.js.org/plugins/html-webpack-plugin/). The same caveats apply as when using `skip_common_chunks` on `render_bundle`, see that section below for more details.
227270

228271
### Rendering by file extension
@@ -309,7 +352,7 @@ The `suffix` option can be used to append a string at the end of the file URL. F
309352

310353
### Multiple Webpack configurations
311354

312-
`django-webpack-loader` also supports multiple Webpack configurations. The following configuration defines 2 Webpack stats files in settings and uses the `config` argument in the template tags to influence which stats file to load the bundles from:
355+
`django-webpack-loader` also supports multiple Webpack configurations. Assuming you have different Webpack configs, each with a different `output.path`, the following configuration defines 2 Webpack stats files in settings and uses the `config` argument in the template tags to influence which stats file to load the bundles from:
313356

314357
```python
315358
WEBPACK_LOADER = {

examples/code-splitting/app/settings.py

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
2222

2323
# SECURITY WARNING: keep the secret key used in production secret!
24-
SECRET_KEY = 'django-insecure-&24ubb46zaej*fd9jz1^mw1t0)-@zd9g74f!hcs1a48-7loo0r'
24+
SECRET_KEY = "django-insecure-&24ubb46zaej*fd9jz1^mw1t0)-@zd9g74f!hcs1a48-7loo0r"
2525

2626
# SECURITY WARNING: don't run with debug turned on in production!
2727
DEBUG = True
@@ -32,63 +32,63 @@
3232
# Application definition
3333

3434
INSTALLED_APPS = [
35-
'django.contrib.admin',
36-
'django.contrib.auth',
37-
'django.contrib.contenttypes',
38-
'django.contrib.sessions',
39-
'django.contrib.messages',
40-
'django.contrib.staticfiles',
41-
'webpack_loader',
35+
"django.contrib.admin",
36+
"django.contrib.auth",
37+
"django.contrib.contenttypes",
38+
"django.contrib.sessions",
39+
"django.contrib.messages",
40+
"django.contrib.staticfiles",
41+
"webpack_loader",
4242
]
4343

4444
MIDDLEWARE = [
45-
'django.middleware.security.SecurityMiddleware',
46-
'django.contrib.sessions.middleware.SessionMiddleware',
47-
'django.middleware.common.CommonMiddleware',
48-
'django.middleware.csrf.CsrfViewMiddleware',
49-
'django.contrib.auth.middleware.AuthenticationMiddleware',
50-
'django.contrib.messages.middleware.MessageMiddleware',
51-
'django.middleware.clickjacking.XFrameOptionsMiddleware',
45+
"django.middleware.security.SecurityMiddleware",
46+
"django.contrib.sessions.middleware.SessionMiddleware",
47+
"django.middleware.common.CommonMiddleware",
48+
"django.middleware.csrf.CsrfViewMiddleware",
49+
"django.contrib.auth.middleware.AuthenticationMiddleware",
50+
"django.contrib.messages.middleware.MessageMiddleware",
51+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
5252
]
5353

54-
ROOT_URLCONF = 'app.urls'
54+
ROOT_URLCONF = "app.urls"
5555

5656
TEMPLATES = [
5757
{
58-
'BACKEND': 'django.template.backends.django.DjangoTemplates',
59-
'DIRS': [os.path.join(BASE_DIR, "templates")],
60-
'APP_DIRS': True,
61-
'OPTIONS': {
62-
'context_processors': [
63-
'django.template.context_processors.debug',
64-
'django.template.context_processors.request',
65-
'django.contrib.auth.context_processors.auth',
66-
'django.contrib.messages.context_processors.messages',
58+
"BACKEND": "django.template.backends.django.DjangoTemplates",
59+
"DIRS": [os.path.join(BASE_DIR, "templates")],
60+
"APP_DIRS": True,
61+
"OPTIONS": {
62+
"context_processors": [
63+
"django.template.context_processors.debug",
64+
"django.template.context_processors.request",
65+
"django.contrib.auth.context_processors.auth",
66+
"django.contrib.messages.context_processors.messages",
6767
],
6868
},
6969
},
7070
]
7171

72-
WSGI_APPLICATION = 'app.wsgi.application'
72+
WSGI_APPLICATION = "app.wsgi.application"
7373

7474

7575
# Database
7676
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
7777

7878
DATABASES = {
79-
'default': {
80-
'ENGINE': 'django.db.backends.sqlite3',
81-
'NAME': BASE_DIR / 'db.sqlite3',
79+
"default": {
80+
"ENGINE": "django.db.backends.sqlite3",
81+
"NAME": BASE_DIR / "db.sqlite3",
8282
}
8383
}
8484

8585

8686
# Internationalization
8787
# https://docs.djangoproject.com/en/3.2/topics/i18n/
8888

89-
LANGUAGE_CODE = 'en-us'
89+
LANGUAGE_CODE = "en-us"
9090

91-
TIME_ZONE = 'UTC'
91+
TIME_ZONE = "UTC"
9292

9393
USE_I18N = True
9494

@@ -100,20 +100,18 @@
100100
# Static files (CSS, JavaScript, Images)
101101
# https://docs.djangoproject.com/en/3.2/howto/static-files/
102102

103-
STATIC_URL = '/static/'
103+
STATIC_URL = "/static/"
104104

105-
STATICFILES_DIRS = (
106-
os.path.join(BASE_DIR, 'assets'),
107-
)
105+
STATICFILES_DIRS = (os.path.join(BASE_DIR, "assets"),)
108106

109107
WEBPACK_LOADER = {
110-
'DEFAULT': {
111-
'BUNDLE_DIR_NAME': 'bundles/',
112-
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json')
108+
"DEFAULT": {
109+
"BUNDLE_DIR_NAME": "webpack_bundles/",
110+
"STATS_FILE": os.path.join(BASE_DIR, "webpack-stats.json"),
113111
}
114112
}
115113

116114
# Default primary key field type
117115
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
118116

119-
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
117+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

examples/code-splitting/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
other: "./assets/js/other",
99
},
1010
output: {
11-
path: path.resolve(__dirname, "assets/bundles/"),
11+
path: path.resolve(__dirname, "assets/webpack_bundles/"),
1212
filename: "[name]-[contenthash].js",
1313
},
1414

0 commit comments

Comments
 (0)