React Integration with Django Using Babel & Webpack
Tags: react, django, javascript, python
Published: 2024-01-03 05:46:10

Hi Devs,

In this post, let's try to add React to our Django Project. It is slightly hectic to remember all the steps, so this post will also help me jot down all of them.

Let me just let you know the Current Directory Structure I am assuming you have before getting started:

```
├── project
│   ├── app
│   │   ├── migrations
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── serializers.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── project
│   │   ├── migrations
│   │   ├── __init__.py
│   │   ├── asgi.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── manage.py
```

Now, we have to make another Django App called `frontend` by typing
```
django-admin startapp frontend
```
Inside the Project Directory.

Then we need to get inside the `frontend` directory and make a few folders inside it for static and templating files. The `apps.py` file in this `frontend` directory is going to store all the kinds of stuff related to our frontend.

And our `frontend` should look like this:
```
├── frontend
│   ├── migrations
│   │   └── __init__.py
│   ├── src
│   │   ├── components
│   │   │   ├── App.js
│   │   │   └── Home.js
│   │   └── index.js
│   ├── static
│   │   ├── css
│   │   ├── frontend
│   │   └── images
│   ├── templates
│   │   └── frontend
│   │       └── index.html
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
```
Now, in the `frontend` directory we will type in the command:
```
npm init -y
```
This is used to initialize a new Node.js project using `npm` with default values. It automatically generates a `package.json` file for your project without prompting you for any input.

Following this, we need to type in these commands:
```
npm i webpack-cli --save-dev
```
The `npm i webpack-cli --save-dev` command installs the `webpack-cli` package as a development dependency. Webpack is a module bundler for JavaScript applications, and `webpack-cli` provides a command-line interface for webpack.
```
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev
```
The `npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev` command installs several Babel-related packages as development dependencies:
- `@babel/core`: This is the core Babel compiler.
- `babel-loader`: This is a webpack loader that allows you to transpile your JavaScript code using Babel during the webpack build process.
- `@babel/preset-env`: This preset allows you to use the latest ECMAScript features and automatically determines the Babel plugins and polyfills needed based on your target environments.
- `@babel/preset-react`: This preset is specifically for React applications. It enables Babel to understand and transform JSX syntax used in React components.
```
npm i react react-dom
```
The `npm install react react-dom` installs React and ReactDOM as regular dependencies, and they will be added to the "dependencies" section of your `package.json` file. React is the library for building user interfaces, and ReactDOM is the package that provides integration with the DOM.
```
npm i @babel/plugin-proposal-class-properties
```
This command installs the Babel plugin `@babel/plugin-proposal-class-properties`. This plugin is used to enable support for class properties in your JavaScript code. Class properties allow you to define properties directly on a class rather than in a constructor.
```
npm i react-router-dom
```
It installs the `react-router-dom package`, which is a package for handling routing in React applications, and will help us reroute the pages so that we can go, well, two different pages from a React App.

Now, after all these, we need to set up some configuration scripts that are going to run and handle our Webpack and our Babel. One can copy these files from here because they are going to be the same thing for everyone.

Firstly, we are going to create a new file in the `frontend` directory named `babel.config.json` and paste the following into it.
```json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "10"
        }
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}
```
Next, create another file and name it as `webpack.config.js` and paste the following into it.
```javascript
const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./static/frontend"),
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },
  optimization: {
    minimize: true,
  },
  plugins: [
    new webpack.DefinePlugin({
      "process.env": {
        // This has effect on the react lib size
        NODE_ENV: JSON.stringify("production"),
      },
    }),
  ],
};
```
Just to let the reader know, what Webpack does is bundle all of our JavaScript into one file. We can bundle it into multiple files, but anyway, it just takes all this JavaScript code we have makes a bundle of it, and then serves that one file to the browser.

Now, let's move on to the next step. We are going to go to `package.json` file and what we need to do inside here is where it says scripts, we need to add two scripts, which are going to run this Webpack. The first thing we're going to add is the dev script. What this is going to do is tell us that, we want Webpack to run, we want to run a neat development mode and we want it to be in watch mode. Next, we're going to add a build script.
```json
"scripts": {
    "dev": "webpack --mode development --watch",
    "build": "webpack --mode production"
}
```

Next up, we are supposed to create an `index.js` file inside the `src` directory. What we need to do now is to make our Django App render a page that React will take control of. If you haven't used Django & React before then this isn't going to make much sense. But what we are up to is to have our Django Application render a template, which is going to be some vanilla, plain HTML, and which our React will take over and fill in. So, we will technically have the Django backend rendering the template but then React will manage it after that. For the time being, let's go to the `index.html` file inside `frontend` folder in `templates` directory and paste the following:
```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Title</title>
    {% load static %}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="{% static "css/index.css" %}"
    />
  </head>
  <body>
    <div id="main">
      <div id="app"></div>
    </div>

    <script src="{% static "frontend/main.js" %}"></script>
  </body>
</html>
```
I don't want to make this very long. So, if you want an explanation of this HTML code, just ask for it in the comments, I will surely help you out.

Once we are done with this, we will move to the `views.py` file. Now, what we are up to may seem a bit weird and strange if you are new, but we need to just render the `index.html` template and then let React take care of it. So, the `views.py` goes like:
```python
# frontend/views.py
from django.shortcuts import render

def index(request, *args, **kwargs):
    return render(request, 'frontend/index.html')
```
Now, it's time for the `urls.py`. Before that make sure that you have included the `frontend.urls` in the `urlpatterns` of the main-project `urls.py` file. Again, if you need help, just comment. However, it should look somewhat like this:
```python
# project/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app/', include('app.urls')),
    path('', include('frontend.urls'))
]
```
This is just an example.

Now, time for our `frontend`'s `urls.py`.
```python
# frontend/urls.py
from django.urls import path
from .views import index

urlpatterns = [
    path('', index),
    # Other URL Patterns...
]
```

Next, we are supposed to make a React component, and therefore we will create an `App.js` file in the `components` directory which kinda goes like this:
```javascript
import React, { Component } from "react";
import { render } from "react-dom";
// import one other component for simplicity
import Home from "./Home";
// import other components if you need them

export default class App extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <Home />
      </div>
    );
  }
}

const appDiv = document.getElementById("app");
render(<App />, appDiv);
```
And now, we just need to import the `./components/App` we created just created to the `index.js` file in the `src` directory.
```javascript
// src/index.js
import App from "./components/App";
```
And now, our entry file imports this file, which runs the code and renders the `App.js` in the `index.html` template.

Finally, What we have to do is to make sure that our servers are running properly because we may have done something wrong in this whole long process. Once our server is running fine, we need to run the script that we had put inside of our `package.json`. So the Webpack module development watch should look at our `index.js` file. It should see that we're importing `App.js`. It should bundle it together. It should output something to static front-end and that file should be calling `main.js`. And then we'll go to the URL endpoint. And now, in the terminal, inside the `frontend` directory, we should run the development server by typing in:
```
npm run dev
```
Finally, make sure to do one thing, which I forget most of the time, eventually, I forgot it even while writing it is that we need to list this `frontend` Django App in the `INSTALLED_APPS` in the `settings.py` file in the main `project` directory.
```python
# project/settings.py

# ...
INSTALLED_APPS = [
    # ...
    'frontend.apps.FrontendConfig',
]
# ...
```
That's done. Feel free to comment or DM me, if you face any difficulties. 
Have a Nice Day Ahead!!
Thank You!