February 29, 2016

Simple Hello World in ReactJS

With Webpack and Gulp

Fork

I wanted to learn and started following a few online guides. It was a bit of a pain getting this going at first since there was a lot of guides online that did different things, while I found the official Facebook guide confusing. So here it is, simple Hello World in ReactJS using webpack and gulp.

The Basics

I assume you know how to use git and npm. Setting these up will not be part of this.

The Dependencies

Install all the dependencies:

npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react file-loader gulp gulp-util react react-dom webpack webpack-dev-server

The Code

Create a new index.html in the src folder. It will be a simple html file with a single bundle.js file that is built by webpack. All the ReactJS rendering will be done inside the content div. The script element needs to be on the bottom of the body tag to ensure the html file is loaded before we start rendering. If we have the script in the head element ReactJS will attempt to render into an element that does not exist yet.

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Hello React!</title>
</head>
<body>
  <div id="content"></div>
  <script src="bundle.js"></script>
</body>
</html>

The jsx file for this example is very short. The requires at the top will define our dependencies. Webpack will use the require definitions to combine all javascript files into our budle.js file that our app references. This is why there is no need to add script tags for any other javascript files. We can also require static files using the webpack file-loader (see line 1). This will copy the static files into our output directory.

1
2
require('file?name=[name].[ext]!./index.html');

var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('content')
);

And thats it for the code. Now we need to build the app.

The Configuration

Before we run our build we will need to configure webpack to use babel loader for the jsx files as well as configure babel with react presets. Ideally the babel config would be in a .babelrc file, but for simplicity we are keeping it within the webpack config file. Create the webpack.config.js in the root of the app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var path = require('path');

module.exports = {
  entry: path.resolve(__dirname, 'src/index.jsx'),
  output: {
    path: path.resolve(__dirname, '_build'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loader: 'babel',
      query:
      {
        presets:['es2015', 'react']
      }
    }]
  },
  plugins: []
};

The Build Pipeline

Now we can do the build using gulp. The gulp file is based on webpack gulp file. For more information about running webpack with gulp see the official docs. There are two main tasks. The default task is used for local dev and runs the webpack dev server and hosts the local files. The server watches all the files and automatically packs them and drops them in the _build folder. The gulp build task runs a production build of the app and drops it into the _build folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var gulp = require("gulp");
var gutil = require('gulp-util');

var webpack = require("webpack");
var WebpackDevServer = require("webpack-dev-server");
var webpackConfig = require("./webpack.config.js");

gulp.task("default", ["webpack-dev-server"]);

gulp.task("build", ["webpack:build"]);
gulp.task("webpack:build", function(callback) {
  // modify some webpack config options
  var myConfig = Object.create(webpackConfig);

  myConfig.plugins = myConfig.plugins.concat(
    new webpack.DefinePlugin({
      "process.env": {
        "NODE_ENV": JSON.stringify("production")
      }
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin()
  );

  webpack(myConfig, function(err, stats) {
    if(err) throw new gutil.PluginError("webpack:build", err);
    gutil.log("[webpack:build]", stats.toString({
      colors: true
    }));
    callback();
  });
});

gulp.task("webpack-dev-server", function(callback) {
  // modify some webpack config options
  var myConfig = Object.create(webpackConfig);
  myConfig.devtool = "eval";
  myConfig.debug = true;
  
  // Start a webpack-dev-server
  new WebpackDevServer(webpack(myConfig), {
    stats: {
      colors: true
    }
  }).listen(4000, "localhost", function(err) {
    if(err) throw new gutil.PluginError("webpack-dev-server", err);
    gutil.log("[webpack-dev-server]", "http://localhost:4000/webpack-dev-server/index.html");
  });
})

The End

Thats all we needed to get a simple ReactJS app up and running. Start the dev server and run locally using default gulp task:

gulp

Browse to http://localhost:4000/_build/ and marvel upon your Hello World app.