Learn the right way to combine Django and ReactJS. This article includes links to a public repository with a fully documented, fully-functional reference project that you can setup in less than an hour and run in your local dev environment using Docker.
If you’re looking for guidance on how to create React pages inside your Django project then you’re in the right place, so please keep reading. I maintain a fully-functional reference project in Github with quick start instructions to get it running locally in your development environment. I highly recommend that you take a look at this repo as part of your research. There are a number of small details codified in the repo which go unmentioned here for the sake of brevity. This article is really just supplemental narrative that explains my design objectives and implementation strategy.
In a nutshell, I wanted seamless integration between React and Django such that the build and test tools that ship with both technologies continue to work without any interference being caused by the presence of either technology. And additionally, I wanted both technologies to not require any special configuration in production. I believe that the method outlined in this article achieves these design goals, and it bears mentioning that as of this writing I’ve not seen this strategy described elsewhere on the Internet. I’m reasonably sure that all of the following are accomplished.:
- Seamless integration between React and Django.
- You can use Django for REST API, user authentications, site headers & footers, admin, and testing
- You can use React on any pages in your project of your choosing.
- All of the build and test tools for both Django and React will continue to work, with no special configuration required.
- You can include popular, complex tooling in your React stack such as Redux, React Router, Bootstrap, etcetera.
- All of the native optimizations in “npm run build” like page chunking will continue to work.
- You can manage all of your code in a single repository
Here’s an example page rendered using this integration methodology. Thanks to name spacing in React along with its quite-impressive build tool, getting React content to appear inside a Django-rendered page is as simple as including the css and js optimized build bundles, and including a div in the html body with an id value that matches that specified in your src/index.js file which in this case is,
document.getElementById('reactjs-root'). Note the following:
- the page header and footer are generated by Django
- the Django debug toolbar is present on the righthand sidebar
- the page itself requires authentication which is managed by Django
- the black interior region is React-created content
Furthermore, as you can see from the html source to the right, the React content is being rendered normally, with the optimized css and js bundles created by React’s
npm run build added to the head section of the DOM, and the standard React hook added to the body element.
To verify that the build chain actually works I’ve modified frontend/src/App.js, adding one image and one line of text. Here’s a link to an archived copy of the complete Django template-rendered html that’s summarized on the right side of the illustration below.
A Bit of Theory
Before we get into the specifics of the technical implementation it behooves us to highlight a couple of React’s architectural principals that weigh on our strategy. First, React handles all file system addressing relative to a project’s root folder, and thus, we can place the root folder anywhere in the file system and React’s build tools will work fine. This should already be apparent to you from your experience building standalone React apps, and this matters in our case because we need to place React’s build output inside of a special Django app that will serve all React content.
Second, a production React build consists entirely of static files, and thus, nearly all of your React content will be served by Django’s built-in django.contrib.staticfiles. We simply need to add some configuration settings to config/settings/base.py to enable staticfile to find the React build. I say nearly all because we’ll ignore React’s build/index.html file at run-time in favor of Django’s templating system, which leads us to the crux element of this integration strategy:
For any Django template-rendered page which we want to include React content we need to implement a Django view and template that adds React’s optimized css and js bundled entry points into the head of the DOM, and adds a div to the body element with id=”reactjs-root”.
Lastly and to that end, we need to understand a couple of superficial aspects of React’s build output (see illustration to the right) that is generated by the command,
npm run build or alternatively,
yarn run build. The structure of React’s build output is fixed and has some defining features such as the folder structures and the locations and names of the css and js entry point bundles which we will reference in a Django view later in this article.
Of particular importance to us is the output file build/asset-manifest.json because its contents describe the relative file paths of the optimized css and js bundles that the build script created, and we need to add links to these two files in the head of our Django template output.