paint-brush
Integrate React.js in a Rails application — the simple wayby@rpechayr
581 reads
581 reads

Integrate React.js in a Rails application — the simple way

by Romain PéchayreAugust 21st, 2015
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

<a href="http://facebook.github.io/react/" target="_blank">React</a> is a great framework for building client side javascript applications. Compared to other client side frameworks, it only takes care of the V in MVC for example. It is quite easy to use it alongside jQuery or backbone.js.
featured image - Integrate React.js in a Rails application — the simple way
Romain Péchayre HackerNoon profile picture

React is a great framework for building client side javascript applications. Compared to other client side frameworks, it only takes care of the V in MVC for example. It is quite easy to use it alongside jQuery or backbone.js.

In the last few months there have been great stuff released around react, like react native, relay, graphql. React has pushed the entire javascript ecosystem to use new tools, write better code and rethink best practices.

One of the new standard related to client side javascript is using CommonJS modules. CommonJS consists of managing dependencies in a safe and explicit way, making it possible for modules to require other modules, like any proper programming language does. The only problem is that it is not supported out of the box by the browser. There are several tools allowing to fix that, including requireJS, browserify and more recently webpack.

Browserify can be used as a standalone toolchain to build a js application (without messing around with gulp or grunt). A good example of that is Facebook flux Todo MVC sample code. Browserify basically creates a bundle.js file out of you react application, and you can then include bundle.js in your index.html page.

Ruby on rails manages javascripts in its own way using the assets pipeline. The assets pipeline is great technology, since you can write modular javascripts, use coffeescript. It can precompile your files for production, etc.

There are two major drawbacks in the assets pipeline though:

  1. It is basically impossible to use it outside of rails. Every time I try to make a standalone assets based ruby app using sinatra for example, after 30 minutes I end up creating a rails app and only use the assets pipeline. This is a big issue, since no one can used this technology outside of ruby on rails, so it will never be a standard technology for front-end development.
  2. It does not work with commonJs modules. The assets pipeline has another way of requiring module, which is quite powerful, but whenever you find a good module on npm, you can’t npm install it and use it in your rails application.

The rails way

There are two common approaches allowing you to use react in rails:

  1. The Rails way. It is greatly documented by @bigardone in a series of blog posts from 2014. He explains how to use the react_rails gem, how to code in JSX + CoffeeScript and guess what ? It works! The great benefit of the react_rails gem is that it allows you to instantiate components from erb and pass props from ruby objects. The main problem of this approach is that it cannot be used with npm modules.
  2. The Rails + browserify way: in order to use react with npm modules, you need a tool like browserify. The browserify-rails gem allows you to require() modules within your standard rails assets. The full approach for react is nicely documented in this article by @olance. This approach is great on paper, but it assumes browserify is installed when compiling your assets. This is not the case if you deploy your app to heroku for example, of if you are using heroku buildpacks. So using this technique implies either having a custom build step for deployment, or precompiling your assets before deploying. You may not want to do this, especially if you are including react in an existing project which assets are precompiled during deployment, and you don’t want to change this in the short term.

The simple way

In my opinion, the approaches described above have great disadvantages, even though they really allow you to do some react code in your rails application. Another approch we could have would be to use browserify in development with a standard package.json file, and make it output a bundle.js file in your rails assets:

  1. First create a simple package.json including react, browserify and reactify like this one:

The devDependencies part can be created incrementally with npm install — save-dev some_library, whereas the dependencies par can be updated using — save option.

2. If you are using turbolinks, your are probably including application.js in the head tag, which is not great for react. So you can create a new js file in /app/assets/javascripts/react/application.js for example and make it as simple as this:

3. Do not forget to add it to your precompiled files by editing /config/application.rb

4. You can then reference this new file in any erb view like a normal javascript:

5. Update your .gitignore. You should ignore node_modules directory as it will not be deployed in production. You should not ignore /app/assets/javascripts/react/bundle.js because you want it to be deployed in production.

6. Work on your react app by running npm start

An extra build step ? You can then work on your react app and get it updated in real time thanks to watchify by running npm start and your js file will be updated in your rails app. The assets pipeline will take care of minifying your file so you don’t have to add extra steps with uglify to build your file for production.

Conclusion

What is interesting about this approach is that it adds a new js file to your rails app, without requiring you to vendor browserify, or vendor your npm modules. You can keep working with jquery and turbolinks for the rest of the app (since you are loading your new js file at the bottom of some erb view). This allows you not to rewrite your whole app and introduce react on a small part of your rails app.

Another benefit is that if you don’t work on the react part, you don’t have to run npm start. On the opposite, if you work on the react part, you will need to run npm start to see the effects of your changes while developing, with no extra steps needed for deployment. So it is impossible to forget to build this javascript before deploying in production.