When I started read about React and Flux thought was a good idea try it out in a sample app to see how the things work in practice and to validate if it could be used in the company I currently work, that now uses ruby for most of the apps.

Everything was fine while I was testing the basic features showed by the docs, then my next move was set up an actual dev environment to give it a shot in a new web app.

This was the moment when the smile on my face simply gone. A lot of new tools, fresh docs and confusion. The struggle was real for a few days until I start to push some code out. Believe me, I tried a lot of different libraries before choose to work with this set, but I won’t provide too much detail on this for now, let’s focus on what’s this post is about.

I will save you the struggle that I had with a friendly step by step, a repo with a simple configuration and the basic structure to your React/Flux project already hot loading your code with Webpack.

- Webpack ? Hot what ?

Calm down, I will present this to you in a way that will be easy, sticking to the basics and showing what you need to know for now to get it working.

What is Webpack ?

Webpack is a module bundler that takes modules with dependencies and generates static assets representing those modules. I strongly suggest that before you proceed take a look at the Webpack Introduction.

It’s a very fast read (serious, it’s 1 min, go and read it) that will give you a better overview about what Webpack does and his differences compared to other module bundlers.

What is Hot Load and Why I Need It ?

Hot Load (or reload if you prefer) is basically your app being updated on browser without you need to refresh the page. But just to give you more a tip of how it works, in our case React Hot Loader will work with the Webpack Hot Module Replacement to make the change in our Webpack modules.

- Did I really need this feature ?

Believe me, after use it for some time, most web development environments will feel slow to you. Don’t even know if it’s good, what am I doing after all ?!

NPM Packages

I’m considering that you already have Node and NPM installed on your machine. That said, we will use this libraries on our package.json:

{
  "name": "simple-react-flux-example",
  "version": "1.0.0",
  "description": "A simple react + flux app example",
  "repository": "https://github.com/wallacyyy/simple-react-flux-example",
  "license": "MIT",
  "scripts": {
    "start": "node server.js"
  },
  "devDependencies": {
    "babel-core": "^5.7.2",
    "classnames": "^2.1.2",
    "flux": "^2.0.1",
    "react": "^0.13.2",
    "react-hot-loader": "^1.2.7",
    "node-sass": "^3.1.0",
    "node-libs-browser": "^0.5.2",
    "webpack": "^1.7.2",
    "webpack-dev-server": "^1.7.0",
    "babel-loader": "^5.0.0",
    "css-loader": "^0.11.0",
    "file-loader": "^0.8.1",
    "sass-loader": "^1.0.1",
    "style-loader": "^0.11.0",
    "url-loader": "^0.5.5"
  }
}

Let’s break down some of the packages that you may asking why they are listed here:

  • babel-core Babel is a transpiler that will transform your javascript ES5 into ES6. This will allow us to use the newest Javascript features in our code even when the browser does not support it yet.

  • classnames ClassNames is an utility library pretty common in the React world, it’s even recommended in the docs, it’s not required but will save you a lot of headache on manipulate dynamic css class names.

  • webpack-dev-server The Webpack has an Express server that serves Webpack bundles. We will use it here, since it’s needed to our hot load. If you want to know more about it take a look at the docs.

  • Loaders: The Webpack only process javascript natively, so you will need a loader for every transformation with some special format requirement you wanna do.

The Webpack’s configuration file

You will add a file in the root of your project named webpack.config.js. This file will have most of the webpack ’s logic. It will look like this:

var path = require('path');
var webpack = require('webpack');

var path = require('path');
var webpack = require('webpack');

module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './src/entry'
  ],

  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/public/'
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],

  resolve: {
    extensions: ['', '.js', '.jsx']
  },

  module: {
    loaders: [
      { test: /\.jsx$/,
        loader: 'react-hot!babel',
        include: path.join(__dirname, 'src') },
      { test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/ },
      { test: /\.scss?$/,
        loader: 'style!css!sass',
        include: path.join(__dirname, 'css') },
      { test: /\.css$/,
        loader: 'style!css' }
    ]
  }
}

Maybe the things started to get weird here, but no problem. Let’s breakdown the important parts of this file:

We will need three entry points respectively: server, hot module replacement and the app’s entry point path.

Entries

entry: [
  'webpack-dev-server/client?http://localhost:3000',
  'webpack/hot/only-dev-server',
  './src/entry'
]

The output is the bundle containing the static assets of our app that Webpack will generate. In this case it’s named bundle.js, this file will be saved on the dist directory. We are adding here the publicPath, that will be used by our server, with this configuration the browser will access:

http://localhost:3000/public/bundle.js

Output

output: {
  path: path.join(__dirname, 'dist'),
  filename: 'bundle.js',
  publicPath: '/public/'
}

Plugins

Let’s add two plugins: Webpack Hot Module Replacement is required to the React Hot Loader replace your modules when they were changed. No Errors will basically stop your bundle if it run into an error. It’s not required but will save you a lot of debugging time.

plugins: [
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin()
]

Loaders

This part is important, because here is where our loaders come into play. With this configuration below we are saying basically this:

Webpack, test if the file has the /\.jsx?$/ extension, if there is, load it with react-hot enable, after that transpile my code from ES5 to ES6 with babel. In your search include only the path.join(__dirname, ‘src’) path.

{ test: /\.jsx?$/,
  loader: 'react-hot!babel',
  include: path.join(__dirname, 'src') }

Let's take a look into another loader using the same strategy:

Webpack, test if the file has the /\.scss?$/ extension, if there is, include the style on my page using the style loader.

The style-loader is used normally combined with the css-loader. Here I'm adding the sass-loader, but it's only a personal choice.

{ test: /\.scss?$/,
  loader: 'style!css!sass',
  include: path.join(__dirname, 'css') }

Loading the bundle

You need to have an initial file on your app that loads the bundle.js generated by the Webpack, so let's include this in our index.html:

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script type="text/javascript" src="/public/bundle.js" charset="utf-8">
    </script>
  </body>
</html>

As you can see we are using the publicPath that we configured on our webpack.config.js.

Configuring the server

Now let's configure the webpack-dev-server that I mentioned earlier. You will add in the root of the project a file named server.js. This file will look like this:

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
}).listen(3000, 'localhost', function (err, result) {
  if (err) { console.log(err) }
  console.log('Listening at localhost:3000');
});

The things are easier here, we are creating a new server instance and listening on the port 3000. Remember our publicPath configuration in the Webpack's configuration file ? Let's use it here and set the flag hot: true to enable the Webpack Hot Module Replacement.

It's Alive !

Now we are good to go. The configuration is not working ? No problem, you can check this repository that I pushed to Github with a simple example. Let's run the npm install and npm start in our project and your server is already running. I did not covered here the React/Flux part, but in the example repository you can see some of these. I will probably enter more in depth of Flux later.

I heard you like GIFs, so here's one of the hot loading in action: