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.
{
"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.
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.
"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:
<!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:
# 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:
# 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
.
# 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:
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.
// 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.
# 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!
Top comments (2)
Awesome post. Thanks for putting it up.
Should in case anyone encounter this error that i got after running
npm run dev
you can resolve by setting NODE_ENV in webpack.config.js from
JSON.stringify("production")
toJSON.stringify("development")
.Completely removing NODE_ENV: JSON.stringify("xxxx") also works fine but i'm uncertain as to what impact that would leave the configurations/application and would appreciate if someone could share
I suppose it should not cause any problems until and unless you are using any plugins that rely on that.