ReactJS with Django - real usage
What if you'd consider the frontend and the backend as two different, independent entities? I mean the following:
- Django should only be an API and respond with json data
- The frontend should be only static files served by nginx
- You may have to deal with CORS in order to allow communication between the two. One option would be to allow preflight requests from your frontend and the other option would be to set up an nginx proxy. This is a separate issue and you should search for it if you need more details.
I think this architecture allows you to keep things separated and not deal with their integration. Things are already too complicated on the frontend/React ecosystem so I think simplicity of config has to be taken into account.
I would also be interested to find out how a deployment process would look for this architecture (what tools to use?), so please add comments if you have suggestions and I'll update the response accordingly to supply useful info for future readers.
I implemented something similar to what you are asking. My front end is entirely on reactjs which is compiled using webpack and my templates are created in django.
So I do following:-
- Use react-router and react to create .jsx/.js code.
- Compile using webpack.
- Use django-webpack
So django-webpack works really nice and helps you isolated you compilation outside of django to get thinks working in a nice and scalable way.
Since you want to use React along with Django templates, I assume the React code will only affect specific parts of your page. The following explanations are written based on that assumption.
First of all, you don't have to put all the JS code in the template — in fact, that would be a mess.
You can create a separate JS-based build process using Webpack (check out this howto). That enhances your client-side code's capabilities, allowing you to use CommonJS modules in the browser, which you can directly pull from npm, including React.
Webpack in turn will generate a bundle (or multiple bundles, depending on the nature of your application and the Webpack configuration) which you'll need to include in your Django templates via <script>
tags as usual.
Now you need to make the React.render()
call to render your React application somewhere in the existing page layout. You'll need to use an empty HTML element with a specific id/class name as a mount point for the application.
But here comes the caveat: you cannot access CommonJS modules directly from the browser or Django templates. So either you,
- expose
React
and your app to thewindow
object, or - create a module with glue code to handle app initialization and expose that method to the
window
object.
In any of the cases you will need to call the initialization code directly from the templates (check out an example of glue code, and the call to app initialization).
This initialization step also allows you to pass variables available in Django templates to the JS code.
The final Django template will look something like this:
{% load staticfiles %}
{% extends 'base.html' %}
{% block scripts %}
<script type="text/javascript" src="{% static 'path/to/app.bundle.js' %}"></script>
<script type="text/javascript">
// Initialization glue code
window.MyApp.init({el: '.app-mountpoint'});
</script>
{% endblock %}
{% block content %}
<!-- Your template contents -->
<!-- The mount point of your app -->
<div class="app-mountpoint" />
{% endblock %}
And the glue code:
var React = require('react');
var MyAppComponent = require('MyAppComponent');
window.MyApp = {
init: function (opts) {
var mountPoint = document.querySelector(opts.el);
React.render(<MyAppComponent />, mountPoint);
}
};
I know all of this might sound overwhelming at the beginning (even more compared to the few steps you had with Angular), but believe me it pays off in the long run.
So summarizing:
- Write React code in separate JS files
- Use Webpack (leveraging CommonJS modules) to bundle your React code
- Include the bundle in your Django templates
- Render the React code using glue code in Django templates