Library / SDK
django-webpack/django-webpack-loader avatar
django-webpack/django-webpack-loader

django-webpack-loader: wiring webpack bundles into Django templates

Transparently use webpack with django

2,536 stars339 forksPythonMIT

At a glance

What is it?
django-webpack-loader reads a webpack-bundle-tracker stats file and renders script and link tags from it, so Django templates never hardcode hashed asset paths. The trade-off is a second build step and a stats file that must exist before Django can render anything.
Who is it for?
Adopt django-webpack-loader if your frontend is already built by webpack and you want Django templates to reference entrypoints by name instead of by hashed filename. Do not adopt it if you are not running webpack, or if you want a single build tool for both sides: this package only reads a stats file, it does not compile anything.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 146 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: hashed bundle names versus Django template tags

Webpack emits filenames like main-9f2c1a.js when content hashing is on, and that hash changes on every build. A Django template that writes <script src="/static/main.js"> breaks the moment the hash changes. django-webpack-loader removes that coupling. The README states the package "consumes a stats file generated by webpack-bundle-tracker and lets you use the generated bundles in Django." You name an entrypoint, not a file, and the tag resolves the current filenames at render time.

The audience is narrow and specific: teams already running webpack who keep their templates in Django rather than in a JavaScript framework. The README points at django-react-boilerplate for a full example project with development and production settings, which tells you the intended shape of the user: a Django app with a React or similar frontend, not a static site generator and not a pure SPA with a separate API. If your frontend already has its own HTML entry point, this package has nothing to do.

How the stats file becomes template output

There are two halves. On the webpack side, the BundleTracker plugin is registered in webpack.config.js and writes a JSON file describing every emitted asset and which entrypoint it belongs to. On the Django side, webpack_loader reads that JSON, filters it, and exposes a template tag.

The README's data flow is a single pass: run webpack, which produces compiled assets and webpack-stats.json; Django templates read the stats file. Nothing flows back. That one-way design is why the package is thin and why it fails loudly when the stats file is stale or missing.

Two settings control the read behaviour. CACHE decides whether the stats file is parsed once and the asset paths kept in memory, or re-read on every render. POLL_INTERVAL sets how often the file is checked for changes during development; the README recommends 0.1 seconds. IGNORE is a list of regular expressions, and any generated file matching one is left out of the template. The README's own example drops hot-update files and source maps. That regex list is the only filtering mechanism, so a build that emits assets you do not want in production has to be handled here or in webpack itself.

Install and first render

Two installs are needed: the tracker lives on the npm side, the loader on the Python side. The README gives both commands.

bash
npm install --save-dev webpack-bundle-tracker

pip install django-webpack-loader

Then register the plugin in webpack.config.js. The README's example sets the output directory, a content-hashed filename, and the stats file location. Note that publicPath is set to "auto", which the README says is "necessary for CDNs/S3/blob storages".

javascript
const path = require("path");
const BundleTracker = require("webpack-bundle-tracker");

module.exports = {
  context: __dirname,
  entry: "./assets/js/index",
  output: {
    path: path.resolve(__dirname, "assets/webpack_bundles/"),
    publicPath: "auto",
    filename: "[name]-[contenthash].js",
  },
  plugins: [
    new BundleTracker({ path: __dirname, filename: "webpack-stats.json" }),
  ],
};

On the Django side, add webpack_loader to INSTALLED_APPS and set the WEBPACK_LOADER dictionary. The recommended block uses DEBUG to decide caching, and points STATS_FILE at the same file the plugin writes.

python
INSTALLED_APPS = (
    ...,
    'webpack_loader',
    ...,
)

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'webpack_bundles/',
        'CACHE': not DEBUG,
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
    }
}

BUNDLE_DIR_NAME must match the webpack output directory inside STATICFILES_DIRS. The README's example sets STATICFILES_DIRS to os.path.join(BASE_DIR, 'assets'), and webpack writes into assets/webpack_bundles/, so the two line up. In development the README suggests running webpack in watch mode in one shell and runserver in another.

bash
npx webpack --mode=development --watch

python manage.py runserver

With the stats file present, the template tag is the whole API. The README's usage example loads it and renders the css group for the main entrypoint.

HTML+django
{% load render_bundle from webpack_loader %}

<html>
  <head>
    {% render_bundle 'main' 'css' %}
  </head>
</html>

The tag accepts the entrypoint name from the stats file, main being webpack's default single-entry shorthand, and emits the script and link tags for everything under it. If the entrypoint name does not exist in the stats file, there is nothing to render and the failure shows up as missing tags rather than a build error.

Caching, polling and the production footgun

The README is explicit that in production with DEBUG=False the stats file is fetched once and POLL_INTERVAL is ignored. That is the right default for immutable hashed assets, and it is also the sharpest edge in the package. If you deploy new bundles without restarting the Django workers, the in-memory asset paths stay pointed at the old filenames. The README does not document rollback or a cache invalidation hook, so a deployment that swaps the stats file underneath a running process is outside what the documentation covers.

The development side has the mirror-image cost. Polling every 0.1 seconds means a stat call on the stats file roughly ten times a second per process while DEBUG is on. That is fine on a laptop and wrong in a shared staging environment where DEBUG was left on.

IGNORE deserves attention too. Because it is applied at render time as a regex against generated filenames, a pattern that is too broad silently drops assets from the page. There is no warning when a file is filtered out.

When this is the wrong tool

If you are not running webpack, this package has no input. It does not bundle, transpile or minify anything; it only reads a JSON file that webpack-bundle-tracker produced. A project using esbuild, Rollup or Vite as its build tool gets nothing from installing it, because none of those write the stats format the loader expects.

A second case: teams that want Django to serve as an API only and let a separate frontend handle its own asset pipeline. The template tag is the entire value proposition, and without Django templates rendering the bundles, there is nothing to use. The README also notes a testing caveat: when render_bundle appears in tests, webpack-bundle-tracker is not running at that point to generate the stats file, so tests need their own arrangement. That is a real friction point for test suites that render full pages.

The version support policy is also worth reading before adopting. The README says Python, Django and Node LTS releases are supported until EOL, and that versions not listed in tests/tox.ini may still work but maintainers will not test them or solve issues with them. That is a clear boundary, not a promise of broad compatibility.

django-webpack-loader compared with a Vite-based pipeline

The closest thing to a like-for-like alternative in the search data is the Vite plus Django combination. The difference is architectural rather than cosmetic. Vite runs a development server with native ES modules and hot module replacement, and the Django integration typically proxies to that server in development and reads a manifest in production. django-webpack-loader does the same manifest-reading job, but the manifest is webpack-stats.json produced by webpack-bundle-tracker, and the development loop is webpack watch plus polling on the stats file.

So the choice follows your bundler, not the loader. If the frontend is already webpack, django-webpack-loader is the smaller change: one npm dev dependency, one plugin entry, one settings dictionary. If you are starting fresh and have no webpack investment, a Vite-based setup avoids the polling model and the stats file entirely. Note that the repository ships a hot-reload example under examples/hot-reload/, so hot reload is available through a specific config rather than being the default path.

Maintenance, licence and upgrade cost

The last push to the repository was on 2026-05-13, and the most recent release listed is 3.2.4 on the same date, following 3.2.3 on 2025-12-10 and 3.2.2 on 2025-11-05. The repository is not archived. The release cadence in that window is patch-level, which suggests maintenance rather than active feature work, and the README's compatibility section points readers at tests/tox.ini as the source of truth for supported versions rather than listing them inline.

The licence is MIT, declared in setup.py as "MIT License" and classified as OSI Approved. For most teams that is the permissive end of the spectrum, but the repository contains both LICENSE and LICENSE.txt at the top level, so check which one your legal review wants to read. Nothing here is legal advice.

Upgrade cost is low in the Python layer, since the public surface is a template tag and a settings dictionary. The coupling that matters is to webpack-bundle-tracker: the loader consumes its output format, so a major change on the tracker side is the upgrade you should watch, not the loader's own version number.

Editorial conclusion

Adopt django-webpack-loader if your frontend is already built by webpack and you want Django templates to reference entrypoints by name instead of by hashed filename. Do not adopt it if you are not running webpack, or if you want a single build tool for both sides: this package only reads a stats file, it does not compile anything. Before committing, verify that webpack-bundle-tracker writes webpack-stats.json to the path you set in STATS_FILE, that BUNDLE_DIR_NAME matches the webpack output directory under STATICFILES_DIRS, and that CACHE is True when DEBUG is False, because in production POLL_INTERVAL is ignored and the stats file is read only once.

Frequently asked questions

What does django-webpack-loader actually do?

It reads the stats file produced by webpack-bundle-tracker and exposes a render_bundle template tag, so Django templates reference an entrypoint name instead of a hashed asset filename. The README describes it as consuming the stats file and letting you use the generated bundles in Django.

How do I install django-webpack-loader?

The README gives two commands: npm install --save-dev webpack-bundle-tracker on the JavaScript side, and pip install django-webpack-loader on the Python side. You then add webpack_loader to INSTALLED_APPS and configure the WEBPACK_LOADER dictionary.

Why does render_bundle show nothing in my template?

The tag resolves names against the stats file, so if webpack-bundle-tracker has not written webpack-stats.json to the path set in STATS_FILE, there is nothing to render. A file matching a pattern in IGNORE is also left out of the template without a warning.

Does django-webpack-loader work in production with DEBUG set to False?

Yes, and the README recommends CACHE set to not DEBUG. In production the stats file is read only once and the asset paths are kept in memory, which means POLL_INTERVAL is ignored and new bundles require the process to pick up the updated stats file.

Official sources

  1. django-webpack/django-webpack-loader on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/django-webpack-django-webpack-loader.svg)](https://hysenlabs.com/projects/django-webpack-django-webpack-loader)