Adding React.js to old Django site (day 4)— React finally :)

Hi guys. Previous 3 days were sacrificed to the gods of preparation. Today I gonna get bless from them and finally plug some React code into my old project.

Previous day is here.

I’m planning to add React.js frontend for private part of my old Django site pokatuha.com. The path full of pain, struggle and monsters. I’m inviting you to join my trip :)

The good news are: I won’t bother Django code for next few days (except one template today) before adding DRF for API. I’ll focus mainly on client side code.

Bad news are: there are preparation gods in React land too. And they need some sacrifices too. I’m talking about npm, Webpack and project structure.

Project structure

In order to keep serverside stuff and clientside separated I need to make some changes for assets folder which is used as source for my webpack.

First of all I’ll move all my old code inside /assets/serverside. I’ll also need to change webpack configuration later to keep it working with old files.

Secondly I need to create folder for my new shiny client app: /assets/clientside.

Now all my work will be done inside /assets/clientside.

There are different approaches on how to structure React.js project. I have no experience with React at all but understand that my app is quite complicated and feature rich so I need to use strict structure. I really like what this guy is proposing.

So here is my structure of /assets category:

serverside/
some old stuff here
clientside/
components/
data/
scenes/
services/
App.js
index.js

/assets/clientside/index.js will be used as entry point for webpack.

Webpack and npm

I already have webpack in my project. It being used for bundling all useful jquery stuff in one single file main.js. Also there is sass pre-processor, text-extraction plugin for making .css files, fonts and images extraction, etc.

Before making any changes I decided to update Webpack to 2.2.0 from my 1.x.x version. It was quite a pain in ass but worth it. Just remember you need to use full names of loaders (‘sass-loader’ instead of ‘sass’, ‘file-loader’ instead of file, etc.) Also some packages for node.js should be updated during this process (sass didn’t work).

In order to keep old javascript code and to add new code for bundling I’m using multiple entry points in Webpack config inside module.exports part:

entry: {
main: './assets/serverside/js/index',
client: './assets/clientside/index'
},
output: {
path: path.resolve('./bundles/'),
filename: 'js/[name].js',
},

After build process I’ll get two js files inside my bundles folder (which is used for collectstatic inside Django): main.js and client.js.

Main.js is old sh*t used for classic serverside rendering of Django. I won’t bother it anymore.

Client.js is new one used for mounting React app.

I also installed dependencies needed for successful react build process in npm:

npm install babel babel-core babel-loader babel-preset-es2015 babel-react-preset react react-dom

Here is how modules looks inside module.exports of webpack configuration file:

module: {
loaders: [
{test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
},

{test: /\.scss$/,
loader: ExtractTextPlugin.extract('css-loader!sass-loader')
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: 'file-loader?name=fonts/[name].[ext]&publicPath=../'
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file-loader?name=img/[name].[ext]&publicPath=../'
]
},
]
},

React finally

It’s time to turn some React.js on! :)

I won’t add any functionality here because the only goal for today is to make all boilerplate dirty job and make React show at least something.

Let’s add some code to /assets/clientside/index.js:

import React, { Component } from 'react';
import ReactDom from 'react-dom';
import App from './App';
ReactDom.render(
<App />,
document.getElementById('app')
);

As you can see I’re importing App.js here. So let’s add App.js into /assets/clientside/:

import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
<h1>It's alive</h1>
<p>Welcome to pokatuha. Let's ride together!</p>
</div>
);
}
};
export default App;

And finally I need to make one small change to Django template which is rendered by my custom middleware:

<!DOCTYPE html>
{% load static compress %}
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="{% static "images/favicon.ico" %}" type="image/ico">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Pokatuha.com - let's ride together</title>
</head>
<body>
<div id="app"></div>
<script type='text/javascript' src="{% static 'js/client.js' %}"></script>
</body>
</html>

That’t all. After running webpack building process all the code is bundled to /bundles/js/client.js which is used by collectstatic of Django. Running Django server and seeing this if the user is authenticated:

Everything is rendered by React.js

Doesn’t look impressive? Yep. But it means a lot! Finally I can start working with React. Hope you enjoyed this trip.

Next day I’m planning to add React Router and plan some Scenes (views) which will be used by my app.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.