How to Build React Applications with Node.js, Jasmine, Babel, and Gulp

Facebook’s React has completely changed the way that I write applications. From my perspective, most javascript frameworks unnecessarily force you into particular programming styles. For example, I often hear people tell me to do things the “angular way” (whatever that means).

This isn’t necessarily a bad thing. Programming standards enable team development. However, I believe that the software architect or the team itself should develop those standards. Framework designers do not know your particular needs and concerns.

In the end, framework designers try to solve their problems. They do not generally care to solve your problems. Many times our problems will overlap with their problems, but it becomes incredibly hard to development when they do not.

We do not always know what designs work at different stages in our software lifecycle; so, we need to have as much control over the design of our applications as possible

In my opinion, React has a much better design simply because it makes much less assumptions.

Consider Angular 1.x. While it is a great framework, it also has an all or nothing philosophy. It is very hard to use it’s data-binding feature without also using its controllers, directives, modules, etc …

React only concerns itself with views.

This makes it possible to create a customized architecture around my particular use cases.

I created simple todo application that demonstrates how you can do this.

I would like to use this blog post to demonstrate in a step-by-step way to build it.

First let’s describe the use case for the application.

Gather the Requirements

Suppose we have the following requirements for our todo application

Use Case 1.0: Add List Items

We expect to give a list item to the application. The application should store this list item, and provide visual feedback that it has stored it.

Use Case 1.1: Detect Invalid List Items

We consider an empty string as invalid input. If we give invalid input we expect the system to detect it and give some visual feedback to the user about it.

Use Case 2.0: Remove List Items

We expect the application to allow us to remove items. The application should provide some visual of all the list items, and it should expose some way to remove individual list items.

When we remove a list item, the application should provide some visual feedback about removing the list item.

Decide on an Tool Set

In order to build the application, we need to make some initial design decisions.

For this tutorial, I decided to build the application in the following tools:

We will put (a) our react code in the “src/view” folder, (b) our node code in the “src/model” and “src/common” folders, (c) our jasmine tests in the “test” folder, and (c) our application into the “app” folder.

Build the Model

Let’s encapsulate the algorithms that fulfill these uses cases into a single node.js module.

Create the following file: src/model/TodoListModel.js.

TodoListModel references another node file called Guid. By design, we force the caller of TodoListModel.addItem to provide a guid as an argument.

I did this to make unit testing easy. We will illustrate unit testing in the next section.

Create the following file: src/common/Guid.js

Create the Unit Tests

We need to validate that TodoListModel actually implements our use cases correctly. We will create separate jasmine specs for each use case.

Create Tests for Use Case 1.0

We want to verify that the model obeys the following constraints when we add list items:

The model adds the list item properly when we add one list item

The model adds list items properly when we add two list items

The model fires events that informs subscribers that the model has added a list item

Create test/AddListItems.spec.js with the following contents to validate that our model obeys the rules for “Use Case 1.0”.

Create Tests for Use Case 1.1

We want to verify that the model obeys the following constraints when we add add list items:

Detect when the caller does not provide a valid list item

Detect when the caller does not provide a valid guid

Verify that the model fires the proper events for an invalid input

Create test/DetectInvalidListItem.spec.js

Create Tests for Use Case 2.0

We want to verify that the model obeys the following constraints when we try to remove items:

The model properly removes one item

The model properly removes 2 of three items

The model fires the proper events when it removes items

Create test/RemoveListItems.spec.js

Execute Unit Tests

We will use gulp to execute our unit tests.

In the main directory, create gulpfile.js with the following contents

Change the NODE_PATH to include ./src. This will ensure that model/TodoListModel.js and common/Guid.js are discoverable.

Our gulp file will now execute our jasmine tests by default. Let’s run it and see the result.

Build the Gulp Workflow

Now that we have a working model let’s build the application. I want to have a very simple deployment. I would like the entire application to run using this html.

I want bundle.js to bootstrap the entire application for index.html.

Let’s modify gulpfile.js to support this.

This will browserify all our react code (which we have not created yet) and package it into bundle.js in the app folder. Further, gulp will use babel to transpile our react code into ES5 javascript. We want to use babel with react because it will provide us with a better syntax than standard javascript.

Build the Views

Create src/Main.jsx with the following contents.

This code shows that we have a UI with three general components:

A message component

An input component

A list component

Further, each component takes a TodoListModel instance as an argument to it’s constructor.

Let’s build out each component one at a time.

Create a MessageArea Component

Create src/view/MessageArea.jsx

Create InputArea Component

Create src/view/InputArea.jsx

Create a TodoList Component

Create src/view/TodoList.jsx

ListBox.jsx creates several ListItems components as children.

Let’s create the component definition.

Create src/view/ListItem.jsx

Build the Application

We can now run gulp.

This gulp build uses babel to transpile the ES6 code into standard javascript and browserfys it into bundle.js in app.

You can open index.html in a browser to execute the application. It should look something like this:

Conclusion

I know that this project is very artificial. I only want you to take away the principles. You ultimately have to make decisions for you applications. Architecting your projects like this may or may not make sense for you.