Configure reactjs with webpack and grunt

So, you wanna bundle your react components using webpack? How about a grunt task that continuously watches the changes that you make to your jsx files and automatically compiles them before webpack bundles them together?

In this post, we are going to do exactly that.

The entire source code for this project is available at github here .

Directory Structure

The project has 3 main parts
– app.js: A simple nodejs http server that literally does nothing but server your static pages.
– public/js/src: The directory where we will keep all our .js and .jsx files.
– public/js/build: The directory where the compiled form of our jsx files are placed and then bundled.
– Two basic html pages: public/index.html , public/anotherPage.html, just to demonstrate how to configure webpack to create one bundle per page.

rootd directory structure

Setting up your package.json
You can look at the package.json file from the github repository. Else, if you are adding it to an existing project, you can run the following commands from your project root to get your dev dependencies right.

npm install --save-dev expose-loader grunt grunt-browserify grunt-cli grunt-contrib-watch grunt-react grunt-webpack webpack nodemon

If you haven’t installed react, you will need to do that as well

npm install --save react

The public/js/src directory
Sicne React mainly deals with components, its nice to have a directory in which you keep all of your components. Here’s how our stuff is organized within the public/js/src directory
components/common : As the name suggests, keep any components reused on multiple pages here.
components/index : Components specific to the index page.
components/index/Page.jsx: The top level React component for the index page.

components/anotherPage: Components specific to the anotherPage page.
components/anotherPage/Page.jsx: The top level React component for the anotherPage page.


The grunt configuration
We are going to keep our grunt file simple by splitting the configuration of each task into their own files and them require them as modules.

rootd directory structure

module.exports = function(grunt) {


  grunt.config( 'webpack', require('./grunt/webpack.js') );
  grunt.config( 'react', require('./grunt/react.js') );
  grunt.config( 'watch', require('./grunt/watch.js') );


  grunt.registerTask('default', ['react']);


Also, make a note of how the keys in the grunt config file are related to the names of the exported files. This is what lets you create different files for different sources.

rootd directory structure

The react task configuration

module.exports = {
    jsx: {
        files: [{
            expand: true,
            cwd: 'public/js/src', // Source Directory
            src: ['**/*.jsx','**/*.js'], // Files to compile
            dest: 'public/js/build', // Destination dir after compile
            ext: '.js'

Webpack configuration

var path = require('path');

module.exports = {
  dev: {
    entry: {
        index: './grunt/webpack_entries/index.js',
        anotherPage: './grunt/webpack_entries/anotherPage.js',
    output: {
        path: path.join(__dirname,'../public/js/build'),
        filename: 'bundle-[name].js'
    stats: {
        // Configure the console output
        colors: true,
        modules: true,
        reasons: true
    progress: true,
    keepalive: true

And finally the configuration for the watch that keeps an eye on file changes
Watch task configuration

module.exports = {
  scripts: {
    files: ['public/js/**/*.jsx', 'public/js/**/*.js'],
    tasks: ['react', 'webpack']

As icing on the cake, if you are usng nodejs, you can configure a script in your package.json to run your first run your tasks and then restart your nodejs application.


"scripts": {
    "build": "grunt react && grunt webpack",
    "dev": "grunt watch & nodemon app"

Using the generated bundles in your html pages
Now that our bundles are generated, open public/index.html and add a script tag with the src property js/build/bundle-index.js since that’s the bundle that is generated for your index. Similary, in anotherPage.html, set the script tag’s src property to js/build/bundle-index.js

One problem that I encountered when I set this up was that the react dev tools plugin did not show up in chrome. Turns out, you need to expose React as a global object for the plugin to work. In order to do that, in our webpack_entires/index.js and webpack_entries/anothePage.js I included a line expose react. Thats the reason why we have expose-loader in our dependency list.


That’s all there is to the setup. Now all you gotta do is run npm run dev from your project root and then stop worrying about having to compile and bundle your changes and restarting your nodejs server after every save.

Ryan Sukale

Ryan is just a regular guy next door trying to manage his life and finances.

You may also like...

3 Responses

  1. Евгений Куртов says:

    thank you for the writeup and git repo!

Leave a Reply to tutorialhorizon Cancel reply

Your email address will not be published. Required fields are marked *