Using Create React App 2 with Django 2

I finally got opportunity to work on a project that used Django together with a React app. There's a combination of packages that help with integrating CRA and Django.

webpack-bundle-tracker + django-webpack-loader

django-webpack-loader and webpack-bundle-tracker work together in the following way. webpack-bundle-tracker plugin emits information about webpack’s compilation process and results so django-webpack-loader can consume it. To add webpack-bundle-tracker to CRA we will need to hook up a plugin to webpack.

CRA configuration

With your CRA app generated we start with react-app-rewired configuration. Rewired uses config-overrides.js file to hook into webpack configuration. There is one more change we have to make apart from adding BundleTracker. The new splitChunks configuration is not entirely supported, so we have to use only named chunks.

var BundleTracker = require('webpack-bundle-tracker')

module.exports = {
  webpack: (config, env) => {
    config.plugins.push(
      new BundleTracker({
        path: __dirname,
        filename: './build/webpack-stats.json',
      })
    )

    config.optimization.splitChunks.name = 'vendors'

    return config
  },
}

After running npm start we should see additional file webpack-stats.json in build folder containing all the data we need.

Django configuration

Install django-webpack-loader using pipenv or pip. Then go to your settings.py. Add webpack_loader to INSTALLED_APPS. This will enable us to use template tags.

INSTALLED_APPS = [
    ...
    'webpack_loader',
]

Project structure

My project directory structure looks like this. I decided to put my CRA app to frontend folder.

├── Pipfile
├── Pipfile.lock
├── README.md
├── my_django_app
│   ├── __init__.py
│   ├── context_processors.py
│   ├── settings.py
│   ├── urls.py
│   ├── utils.py
│   └── wsgi.py
├── frontend
│   ├── build
│   ├── config-overrides.js
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   └── src
└── manage.py

With following structure, we can configure webpack loading in following way.

STATICFILES_DIRS = [
    # So Django knows about webpack files
    os.path.join(BASE_DIR, "frontend", "build", "static"),
]

WEBPACK_LOADER = {
    "DEFAULT": {
        "CACHE": not DEBUG,
        "BUNDLE_DIR_NAME": "frontend/build/static/",  # must end with slash
        "STATS_FILE": os.path.join(BASE_DIR, "frontend", "build", "webpack-stats.json"),
    }
}

Usage

In our Django template we can then use render_bundle to load our CRA app.


{% load render_bundle from webpack_loader %}
{% render_bundle 'vendors' %}
{% render_bundle 'main' %}
{% render_bundle 'runtime~main' %}

It will also display the webpack error when the build process is failing.

I was very happy about getting Django and CRA to work together in this way and I can only recommend it.

Projects