Artem Shalagin
Artem Shalagin

Reputation: 157

Django + React production setup

It looks like a very basic question and I'm confused by the fact that I cannot find any sensible tutorial on that. I'm trying to setup Django + React production build. After running all kinds of transpilation, minification etc. I end up having .js and .css bundles, index.html and several other files like favicon, service-worker.js etc. Now I need to serve this with Django.

All of these files are static files and should probably be served as static files by the http server (nginx in my case). The variant I came up with was to modify index.html to make it a valid Django template: {% load static %} in the beginning, replace all hardcoded links with {% static 'filepath' %} and serve it using TemplateView, other files are served by nginx. This works fine, however, modifying build results looks like a bad idea. Generated bundles contain a unique hash for each build and I would need to replace that hash in the template after each build. I obviously can automate it but it looks weird. I would prefer not to touch build results at all, but how should I serve static files then? nginx is configured to serve static files under /static/ path and cannot serve files like service-worker.js as static files.

So the question is how do I configure Django + React for production so that I don't have to manually modify build results and can serve static files properly using nginx?

Upvotes: 1

Views: 1035

Answers (1)

The main problem to combine React and Django is that Django wants to render the templates by itself, but React wants also to execute the render, since it has been created for that. That's why there a lot of approximations that use django just as as REST API when working with react.

But, if you want django to Render the templates to avoid having a Single Page Application (as react provides) and to use all the other tools from django, the main flow that we use in our company is:

  1. You create your components, in js files. For example: component.js

  2. You use babel to compile the JSX files to native Javascript, and babels creates, for example, component.build.js. Django will serve this compiled files, so react is going to be used only in develop tasks because all React code will be transformed to JS before moving to production. For django, all the react components will be just JS code already compiled.

  3. You can use Webpack to automatically move component.build.js to a folder where django can serve them, for example your_project/static/your_app/component.buid.js

  4. You create a django template base.html which will be used as the base template that all your templates will extend. Here you put the header and all your common scripts and styles. For example, bootstrap should be here if used. Remember to leave blocks in this base template to use them in the templates that are going to extend the base.html. Here is the base.html that we use:

{% with version="2.0" %}
<!DOCTYPE html>
{% load static %}
<html>

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="author" content="">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- base styles goes here -->
  <!-- include here bootstrap or styles that are common to all your website -->
  <link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
  <!-- custom styles for each app go into this block-->
  {% block app_styles %}
  <!-- here will go the apps local styles -->
  {% endblock %}

</head>

<body>

  {% block app %}
  <!-- This block will be used by the apps to load their react components -->
  {% endblock %}

  <!-- base js go here -->
  <script src="{% static 'common/pluggins/jquery3.4.1.min.js' %}"></script>
  </script>
  <script src="{% static 'common/pluggins/fontawesome.js' %}"></script>
  <script src="{% static 'common/scripts/base.js' %}?v={{version}}"></script> <!-- File for common utils -->
  <!-- custom js for each app go here. You should define your Content() here -->

  {% block local_scripts %}
  <!-- here will go the app local scripts -->
  {% endblock %}

  
</body>

</html>
{% endwith %}

  1. Create the templates for each of your django apps, by extending the base.html. Remember to include here the <div> that is going to be used by react to render the content. Aslo, remember that this is the place to include the component.build.js compiled JS file that bable created before. Here there is an example that we use to build a dashboard.html in our website:

{% extends 'common/base.html' %}
{% load static %}

{% block app_styles %}
    <link rel="stylesheet" href="{% static 'dashboard/styles/dashboard.css' %}?v={{version}}">
{% endblock %}

{% block app %}
    <!-- Here is the div used by react --> 
    <div id="myreact-content"></div>
{% endblock %}

{% block local_scripts %}
    <!-- IMPORTANT: Import here the compiled file -->
    <script src="{% static 'component.build.js' %}"></script>
{% endblock %}

  1. Set the correct urls.py in your projects and in your app

  2. Set the correct configuration in setting.py to make accesible the static js/css files and the templates

Run your django server and You're done!

In this video you have a small guide on how to configure npm, babel and django. With a correct configuration, everything will be updated automatically when you change some code in your JSX (not compiled) files, so the develop tasks will be more friendly. https://www.youtube.com/watch?v=Mx3ChaYA0Gw

Upvotes: 1

Related Questions