• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

django_webpack_loader.egg-info/H03-May-2022-437311

webpack_loader/H24-Feb-2020-360264

LICENSEH A D11-Jan-20201.1 KiB2317

MANIFEST.inH A D11-Jan-202034 32

PKG-INFOH A D24-Feb-202016.7 KiB437311

README.mdH A D24-Feb-202012.7 KiB416291

setup.cfgH A D24-Feb-202080 85

setup.pyH A D11-Jan-20201.3 KiB4233

README.md

1# django-webpack-loader
2
3[![Join the chat at https://gitter.im/owais/django-webpack-loader](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/owais/django-webpack-loader?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4[![Build Status](https://circleci.com/gh/owais/django-webpack-loader/tree/master.svg?style=svg)](https://circleci.com/gh/owais/django-webpack-loader/tree/master)
5[![Coverage Status](https://coveralls.io/repos/owais/django-webpack-loader/badge.svg?branch=master&service=github)](https://coveralls.io/github/owais/django-webpack-loader?branch=master)
6
7<br>
8
9Read http://owaislone.org/blog/webpack-plus-reactjs-and-django/ for a detailed step by step guide on setting up webpack with django using this library.
10
11
12Use webpack to generate your static bundles without django's staticfiles or opaque wrappers.
13
14
15Django webpack loader consumes the output generated by [webpack-bundle-tracker](https://github.com/owais/webpack-bundle-tracker) and lets you use the generated bundles in django.
16
17A [changelog](CHANGELOG.md) is also available.
18
19
20## Compatibility
21
22Test cases cover Django>=1.6 on Python 2.7 and Python>=3.4. 100% code coverage is the target so we can be sure everything works anytime. It should probably work on older version of django as well but the package does not ship any test cases for them.
23
24
25## Install
26
27```bash
28npm install --save-dev webpack-bundle-tracker
29
30pip install django-webpack-loader
31```
32
33<br>
34
35## Configuration
36
37<br>
38
39### Assumptions
40
41Assuming `BASE_DIR` in settings refers to the root of your django app.
42```python
43import sys
44import os
45
46BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
47```
48
49<br>
50
51Assuming `assets/` is in `settings.STATICFILES_DIRS` like
52
53```python
54STATICFILES_DIRS = (
55    os.path.join(BASE_DIR, 'assets'),
56)
57```
58
59<br>
60
61Assuming your webpack config lives at `./webpack.config.js` and looks like this
62```javascript
63var path = require('path');
64var webpack = require('webpack');
65var BundleTracker = require('webpack-bundle-tracker');
66
67module.exports = {
68  context: __dirname,
69  entry: './assets/js/index',
70  output: {
71      path: path.resolve('./assets/webpack_bundles/'),
72      filename: "[name]-[hash].js"
73  },
74
75  plugins: [
76    new BundleTracker({filename: './webpack-stats.json'})
77  ]
78}
79```
80
81
82<br>
83
84### Default Configuration
85```python
86WEBPACK_LOADER = {
87    'DEFAULT': {
88        'CACHE': not DEBUG,
89        'BUNDLE_DIR_NAME': 'webpack_bundles/', # must end with slash
90        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
91        'POLL_INTERVAL': 0.1,
92        'TIMEOUT': None,
93        'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
94        'LOADER_CLASS': 'webpack_loader.loader.WebpackLoader',
95    }
96}
97```
98
99<br>
100
101#### CACHE
102```python
103WEBPACK_LOADER = {
104    'DEFAULT': {
105        'CACHE': not DEBUG
106    }
107}
108```
109When `CACHE` is set to True, webpack-loader will read the stats file only once and cache the result. This means web workers need to be restarted in order to pick up any changes made to the stats files.
110
111<br>
112
113#### BUNDLE_DIR_NAME
114```python
115WEBPACK_LOADER = {
116    'DEFAULT': {
117        'BUNDLE_DIR_NAME': 'bundles/' # end with slash
118    }
119}
120```
121
122`BUNDLE_DIR_NAME` refers to the dir in which webpack outputs the bundles. It should not be the full path. If `./assets` is one of your static dirs and webpack generates the bundles in `./assets/output/bundles/`, then `BUNDLE_DIR_NAME` should be `output/bundles/`.
123
124If the bundle generates a file called `main-cf4b5fab6e00a404e0c7.js` and your STATIC_URL is `/static/`, then the `<script>` tag will look like this
125
126```html
127<script type="text/javascript" src="/static/output/bundles/main-cf4b5fab6e00a404e0c7.js"/>
128```
129
130**NOTE:** If your webpack config outputs the bundles at the root of your `staticfiles` dir, then `BUNDLE_DIR_NAME` should be an empty string `''`, not `'/'`.
131
132<br>
133
134#### STATS_FILE
135```python
136WEBPACK_LOADER = {
137    'DEFAULT': {
138        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json')
139    }
140}
141```
142
143`STATS_FILE` is the filesystem path to the file generated by `webpack-bundle-tracker` plugin. If you initialize `webpack-bundle-tracker` plugin like this
144
145```javascript
146new BundleTracker({filename: './webpack-stats.json'})
147```
148
149and your webpack config is located at `/home/src/webpack.config.js`, then the value of `STATS_FILE` should be `/home/src/webpack-stats.json`
150
151<br>
152
153#### IGNORE
154`IGNORE` is a list of regular expressions. If a file generated by webpack matches one of the expressions, the file will not be included in the template.
155
156<br>
157
158#### POLL_INTERVAL
159
160`POLL_INTERVAL` is the number of seconds webpack_loader should wait between polling the stats file. The stats file is polled every 100 miliseconds by default and any requests to are blocked while webpack compiles the bundles. You can reduce this if your bundles take shorter to compile.
161
162**NOTE:** Stats file is not polled when in production (DEBUG=False).
163
164<br>
165
166#### TIMEOUT
167
168`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.
169
170<br>
171
172#### LOADER_CLASS
173
174`LOADER_CLASS` is the fully qualified name of a python class as a string that holds the custom webpack loader.
175This is where behavior can be customized as to how the stats file is loaded. Examples include loading the stats file
176from a database, cache, external url, etc. For convenience, `webpack_loader.loader.WebpackLoader` can be extended;
177The `load_assets` method is likely where custom behavior will be added. This should return the stats file as an object.
178
179Here's a simple example of loading from an external url:
180
181```py
182# in app.module
183import requests
184from webpack_loader.loader import WebpackLoader
185
186class ExternalWebpackLoader(WebpackLoader):
187
188  def load_assets(self):
189    url = self.config['STATS_URL']
190    return requests.get(url).json()
191
192
193# in app.settings
194WEBPACK_LOADER = {
195  'DEFAULT': {
196      'CACHE': False,
197      'BUNDLE_DIR_NAME': 'bundles/',
198      'LOADER_CLASS': 'app.module.ExternalWebpackLoader',
199      # Custom config setting made available in WebpackLoader's self.config
200      'STATS_URL': 'https://www.test.com/path/to/stats/',
201  }
202}
203```
204
205<br>
206
207## Usage
208<br>
209
210### Manually run webpack to build assets.
211
212One of the core principles of django-webpack-loader is to not manage webpack itself in order to give you the flexibility to run webpack the way you want. If you are new to webpack, check one of the [examples](https://github.com/owais/django-webpack-loader/tree/master/examples), read [my detailed blog post](http://owaislone.org/blog/webpack-plus-reactjs-and-django/) or check [webpack docs](http://webpack.github.io/).
213
214
215### Settings
216
217Add `webpack_loader` to `INSTALLED_APPS`
218
219```
220INSTALLED_APPS = (
221    ...
222    'webpack_loader',
223)
224```
225
226### Templates
227
228```HTML+Django
229{% load render_bundle from webpack_loader %}
230
231{% render_bundle 'main' %}
232```
233
234`render_bundle` will render the proper `<script>` and `<link>` tags needed in your template.
235
236`render_bundle` also takes a second argument which can be a file extension to match. This is useful when you want to render different types for files in separately. For example, to render CSS in head and JS at bottom we can do something like this,
237
238```HTML+Django
239{% load render_bundle from webpack_loader %}
240
241<html>
242  <head>
243    {% render_bundle 'main' 'css' %}
244  </head>
245  <body>
246    ....
247    {% render_bundle 'main' 'js' %}
248  </body>
249</head>
250```
251
252<br>
253
254
255### Multiple webpack projects
256
257Version 2.0 and up of 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.
258
259```python
260WEBPACK_LOADER = {
261    'DEFAULT': {
262        'BUNDLE_DIR_NAME': 'bundles/',
263        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
264    },
265    'DASHBOARD': {
266        'BUNDLE_DIR_NAME': 'dashboard_bundles/',
267        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-dashboard.json'),
268    }
269}
270```
271
272```HTML+Django
273{% load render_bundle from webpack_loader %}
274
275<html>
276  <body>
277    ....
278    {% render_bundle 'main' 'js' 'DEFAULT' %}
279    {% render_bundle 'main' 'js' 'DASHBOARD' %}
280
281    <!-- or render all files from a bundle -->
282    {% render_bundle 'main' config='DASHBOARD' %}
283
284    <!-- the following tags do the same thing -->
285    {% render_bundle 'main' 'css' 'DASHBOARD' %}
286    {% render_bundle 'main' extension='css' config='DASHBOARD' %}
287    {% render_bundle 'main' config='DASHBOARD' extension='css' %}
288
289    <!-- add some extra attributes to the tag -->
290    {% render_bundle 'main' 'js' 'DEFAULT' attrs='async charset="UTF-8"'%}
291  </body>
292</head>
293```
294
295### File URLs instead of html tags
296
297If you need the URL to an asset without the HTML tags, the `get_files`
298template tag can be used. A common use case is specifying the URL to a
299custom css file for a Javascript plugin.
300
301`get_files` works exactly like `render_bundle` except it returns a list of
302matching files and lets you assign the list to a custom template variable. For example,
303
304```HTML+Django
305{% get_files 'editor' 'css' as editor_css_files %}
306CKEDITOR.config.contentsCss = '{{ editor_css_files.0.publicPath }}';
307
308<!-- or list down name, path and download url for every file -->
309<ul>
310{% for css_file in editor_css_files %}
311    <li>{{ css_file.name }} : {{ css_file.path }} : {{ css_file.publicPath }}</li>
312{% endfor %}
313</ul>
314```
315
316### Refer other static assets
317
318`webpack_static` template tag provides facilities to load static assets managed by webpack
319in django templates. It is like django's built in `static` tag but for webpack assets instead.
320
321
322In the below example, `logo.png` can be any static asset shipped with any npm or bower package.
323
324```HTML+Django
325{% load webpack_static from webpack_loader %}
326
327<!-- render full public path of logo.png -->
328<img src="{% webpack_static 'logo.png' %}"/>
329```
330The public path is based on `webpack.config.js` [output.publicPath](https://webpack.js.org/configuration/output/#output-publicpath).
331
332<br>
333
334### From Python code
335
336If you want to access the webpack asset path information from your application code then you can use
337the function in the `webpack_loader.utils` module.
338
339```python
340>>> utils.get_files('main')
341[{'url': '/static/bundles/main.js', u'path': u'/home/mike/root/projects/django-webpack-loader/tests/assets/bundles/main.js', u'name': u'main.js'},
342 {'url': '/static/bundles/styles.css', u'path': u'/home/mike/root/projects/django-webpack-loader/tests/assets/bundles/styles.css', u'name': u'styles.css'}]
343>>> utils.get_as_tags('main')
344['<script type="text/javascript" src="/static/bundles/main.js" ></script>',
345 '<link type="text/css" href="/static/bundles/styles.css" rel="stylesheet" />']
346```
347
348## How to use in Production
349
350**It is up to you**. There are a few ways to handle this. I like to have slightly separate configs for production and local. I tell git to ignore my local stats + bundle file but track the ones for production. Before pushing out newer version to production, I generate a new bundle using production config and commit the new stats file and bundle. I store the stats file and bundles in a directory that is added to the `STATICFILES_DIR`. This gives me integration with collectstatic for free. The generated bundles are automatically collected to the target directory and synched to S3.
351
352
353`./webpack_production.config.js`
354```javascript
355var config = require('./webpack.config.js');
356var BundleTracker = require('webpack-bundle-tracker');
357
358config.output.path = require('path').resolve('./assets/dist');
359
360config.plugins = [
361    new BundleTracker({filename: './webpack-stats-prod.json'})
362]
363
364// override any other settings here like using Uglify or other things that make sense for production environments.
365
366module.exports = config;
367```
368
369`settings.py`
370```python
371if not DEBUG:
372    WEBPACK_LOADER.update({
373        'BUNDLE_DIR_NAME': 'dist/',
374        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json')
375    })
376```
377
378<br><br>
379
380
381You can also simply generate the bundles on the server before running collectstatic if that works for you.
382
383## Extra
384
385### Jinja2 Configuration
386
387If you need to output your assets in a jinja template we provide a Jinja2 extension that's compatible with the [Django Jinja](https://github.com/niwinz/django-jinja) module and Django 1.8.
388
389To install the extension add it to the django_jinja `TEMPLATES` configuration in the `["OPTIONS"]["extension"]` list.
390
391```python
392TEMPLATES = [
393    {
394        "BACKEND": "django_jinja.backend.Jinja2",
395        "OPTIONS": {
396            "extensions": [
397                "django_jinja.builtins.extensions.DjangoFiltersExtension",
398                "webpack_loader.contrib.jinja2ext.WebpackExtension",
399            ],
400        }
401    }
402]
403```
404
405Then in your base jinja template:
406
407```HTML
408{{ render_bundle('main') }}
409```
410
411--------------------
412<br>
413
414
415Enjoy your webpack with django :)
416