Building robust web apps with React: Part 2, optimising with Browserify

In part 1 I covered the reasons why I think React is an exciting tool that can be used to build isomorphic or adaptive-hybrid websites which can equal the dynamism of a smart phone application and be as robust as a 20 year old static page. I also wrote a basic demo application to explore some of Reacts paradigms and features and to show how quickly dynamic applications can be prototyped in-browser but it was hardly a display of the robustness I’m primarily striving for.

The code being delivered to the browser in the initial demo failed every basic web performance test; the scripts should to be precompiled, concatenated and minified before being delivered on a production website.

Precompiling the code from the JSX syntax to plain JavaScript can be done with the command line React Tools which is installed as an NPM package:

$ npm install -g react-tools

React Tools can perform a one-to-one .jsx to .js file conversion and it is smart enough to recognise CommonJS require statements to build the dependency tree for a project. This means the tool can process an entire application when given only a single entry point, so there’s no need to transform each script individually. The Tube Tracker application could be transformed with the following command once each scripts dependencies are defined, making sure to start with the files with a .jsx extension:

$ jsx --follow-requires -x jsx app/ public/scripts/

The React Tools solve one piece of the puzzle but the individual scripts still need concatenating and then minifying. Usually when working with a build process requiring several steps a task runner such as Grunt or Gulp.js would be useful but with such a simple application–and one intended to run on both the server and in the browser–we can just use the module bundler Browserify and NPM package scripts for orchestration.

Browserify logo

Browserify enables developers to write separate CommonJS style modules which are compatible with the module system used by Node.js, with the intention of compiling them into single files for the browser. Browserify also includes browser specific versions of certain Node.js core modules and it’s even used by the React project itself to create distributable versions of the library. It’s a good tool to use in an all-JavaScript environment because with some careful decisions it allows code to be re-used for both the front and back end of an application.

We don’t need a task runner because Browserify supports extensions or ‘source transforms’ through which it can pipe each script it processes. There are transforms available for both precompiling JSX (Reactify) and minifying the output (Uglifyify). All the packages can be installed via NPM, making sure to save them as dependencies to the package manifest:

$ npm install --save-dev browserify reactify uglifyify

The build process can now be run but to save repetitively typing the commands they can also be saved to the package manifest as package scripts. NPM already has shortcuts for common use cases such as npm test and npm start and arbitrary development and production build scripts can be defined to execute Browserify with the appropriate transforms and flags:

{
  
  "scripts": {
    "build-dev": "browserify -e app/bootstrap.js -t reactify -o public/scripts/bundle.dev.js -d",
    "build-min": "browserify -e app/bootstrap.js -t reactify -t uglifyify -o public/scripts/bundle.min.js"
  }
}
~/package.json

The two package scripts can then be run in sequence:

$ npm run build-dev && npm run build-min

Lastly, as a handy feature I’ve setup an internal redirect within the application server (written with Express) to deliver the correct script bundle depending on the environment the application is running in:

app.set("js", app.get("env") === "development" ? "dev" : "min");

app.use(function (req, res, next) {
  if (req.url === "/scripts/bundle.js") {
    req.url = "/scripts/bundle." + app.get("js") + ".js";
  }

  next();
});
~/server.js

Honestly, it hasn’t taken me an entire month to write this short article but explaining how to test an application built with React turned out to be a bit more work than expected. I’ve split my testing explorations into part 3. You can test the app right now (note: It’s running on a free account so this link may not be reliable) or head over to GitHub to check out the source code. Please leave a comment or send me a tweet, I’d love some feedback.

View the project on GitHub