The simplest way to run Webpack on Django and Heroku

Sometimes you just need to get a simple, single-file Webpack installation on your Django application. By the end of this guide, you will have a webpack installation that compiles and serves a single file. It will support live reloading on your local development environment, and will be compiled and served as part of the build phase on your Heroku application.

While this configuration is only designed to compile and serve one file, it is trivial to extend the Webpack configuration to serve multiple files. If your application is simple enough, you may find that including a few dependencies and custom JS files into your one file is good enough.

Setting up Django

Set up a static folder in the main app of you Django project and add a main.js file, which will contain all of your JS. Add a dist folder, which will contain the compiled version of this file. We will use app as the convention for this guide, but this should be renamed to whichever app you wish to use as the location for your main.js file

mkdir app/static
touch app/static/main.js
mkdir app/static/dist

Add the compiled script to your main template file

{% load static %}
<script src="{% static 'dist/main.js' %}"></script>

Initializing Webpack

Initialize a new Node.js project and install Webpack into your bundle

npm init -y
npm install --save-dev webpack webpack-cli

Create a new file in your project root named webpack.config.js and add the following basic configuration:

const path = require('path');

module.exports = {
    entry: './app/static/main.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'app/static/dist'),
    }
};

This configuration takes the main.js file you created in your main app application and outputs it to a compiled file in app/static/dist

Configuring Heroku

Heroku picks the buildpack it uses to compile your project automatically, but it will get confused if it sees both a package.json and requirements.txt file in the repository. You must therefore configure Herkou to explicitly state that you are runnning both a JS and Python project and need both buildpacks to be set up.

heroku buildpacks:clear
heroku buildpacks:add --index 1 heroku/nodejs
heroku buildpacks:add --index 2 heroku/python

Add the following to your package.json file

"scripts": {
    "dev": "webpack --watch",
    "build": "webpack",
    "heroku-postbuild": "npm run build"
},

This will allow you to run webpack once via the npm run build command, in watch mode - rebuilding on changes - via npm run dev, and will configure Heroku to run webpack as part of the build phase.

Add dist to your .gitignore file so that the compiled version is not commite to the repository. We will create it as part of the build phase when deploying to Heroku

# ...
.env
db.sqlite3
# ... other .gitinore values
dist
# ^ add this

Running on development and production

You should be all set! Your bundle should be automatically compiled and deployed when you push to Heroku. You can run a development version of webpack locally by running one of the following commands:

npm run dev     # runs webpack in watch mode, monitoring for changes and reloading
npm run build   # runs webpack once

Configuring HTMX and Alpine.JS to run on Django develompent and Herkou production servers

You may not need this, but the addition of HTMX and Alpine.JS to Django make it easy to build modern, responsive applications. Here's how you can set up your bundle to serve these files:

Install Alpine and HTMX

npm install alpinejs htmx.org

Add them to your main.js bundle

import Alpine from 'alpinejs'
import htmx from 'htmx.org';


window.Alpine = Alpine
window.htmx = htmx;

Alpine.start()

It's that easy!