In part two, we setup the link between Django and ReactJS with the help of Webpack. We need to run three commands just to quickly reload a server and view UI changes. In this guide, we will setup react-hot-loader to allow live changes to be reflected on our Django application that is showing the react components.

If needed, please revisit part two. You can also checkout the part3 branch here to continue.

Step 1: Update webpack config

We will need to update web pack config to use react-hot-loader.

Update the entry to this:

entry:[
	'react-hot-loader/patch',
	'webpack-dev-server/client?http://localhost:3000/',
	'webpack/hot/only-dev-server',
	'./assets/static/js/index',
],

output should be updated to:

output: {
  path: path.resolve('./apps/static/bundles/'),
  filename: '[name]-[hash].js',
  publicPath: 'http://localhost:3000/static/bundles/',
},

Then finally plugins to:

plugins: [
	new webpack.HotModuleReplacementPlugin(),
	new webpack.NoEmitOnErrorsPlugin(),
	new BundleTracker({filename: './webpack-stats.json'}),
],

What we are doing here are updating the config of webpack to cater for react-hot-loader. These are just a bunch of settings to follow. You can visit webpack and react-hot-loader to learn more. What you need to know is, during development, instead of going to usual directory to read static files, we are now going to localhost:3000.

Since we are using react-hot-loader v3 we need to update .babelrc:

{
  "presets": ["react"],
  "plugins": ["react-hot-loader/babel"]
}

Step 2: Watch for changes

Now instead of recompiling whenever we make a change, we will run a server to do it.

Create a server.js file in root directory.

var webpack = require('webpack')
var WebpackDevServer = require('webpack-dev-server')
var config = require('./webpack.config')

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  inline: true,
  historyApiFallback: true,
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
}).listen(3000, '0.0.0.0', function (err, result) {
  if (err) {
    console.log(err)
  }
  console.log('Listening at 0.0.0.0:3000')
})

Once that is completed, we can run the server with either of the command below:

$ node server.js		#either this or
$ npm run watch 		#where we setup this in part 1

Step 3: Update the index.js

Now, because we are using react-hot-loader, we need to update index.js and move any component that could possibility change to another file.

Update index.js to this:

import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './App'

const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <Component />
    </AppContainer>,
    document.getElementById('app')
  )
}
render(App)
if (module.hot) {
  module.hot.accept('./App', () => { render(App) })
}

The above are the exact configuration we take from the github docs. Next, we will need to create a new App.js that we are importing here.

import React from 'react';

const App = () => {
    return (
      <div>
      <h1>Hello World!</h1>
    </div>
    );
}
export default App;

Thats all we need. Now ReactJS component live inside Django and with the help of webpack and react-hot-loader we can have a better development environment.

See hot loader in action:

Just run npm run watch and another python manage.py runserver. Keep the two session running while coding. This is what we will see:

Use in Production

In production, we does not need to use react-hot-loader. Therefore we should have a separate file called wepack.prod.config.js. This is what i have inside it:

var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')

module.exports = {
  context: __dirname,
  entry: [
      './assets/static/js/index'
  ],
  output: {
      path: path.resolve('./assets/static/bundles/'),
      filename: '[name]-[hash].js',
  },
  plugins: [
    new BundleTracker({filename: './webpack.prod-stats.json'}),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
    }}),
    new webpack.optimize.OccurrenceOrderPlugin(),
  ],
  module: {
    loaders: [
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader'], },
    ],
  },
  resolve: {
    modules: [
      'node_modules',
      'bower_components'
    ],
    extensions: ['.js', '.jsx']
  }
}

Basically the different is there is no react-hot-loader config and we also added a few plugin to remove debug code.

To run on production, ensure that the step of npm run build-prod is run before collectstatic when in production.

References

Most of the content that I have here are gather from various sources when trying to implement ReactJS into my Django project.

Where to go from here

ReactJS is very much just another way to render view. It is not another MVC framework. In order to show is full potential, it need to be somehow connected with a backend services. Here, I am directly rendering it with a Django backend. However there are a lot more different setup, like using it with redux or flux.

Live Production Example!

In the very same blog, the App Page are build with the same setup that I described here.