In this article, we’ll talk about React and Rails integration and what the react_webpack_rails gem can help you with.

Motivation

It all started during the React Europe conference. We went there, we saw amazing things, and we loved it. We hope that this rapidly developing framework will find a home with our current technologies. But how can it fit into our Rails applications? Until now, we've been using Backbone or Angular to deal with complicated JavaScript in Rails Views (well, and Ember for SPAs).

Why invest your time and efforts into React?

A lot of people feel that React has a better learning curve than Angular or Backbone. A lot of research has also been done about its speed. However, what we really appreciated in React is the isolation of the view layer and the encapsulation of responsibilities. Using React, you can expect safe and easily understood data flow.

Last but not least, we want to stay DRY and reuse a code base that we find stable and reliable. In most of our Rails applications, we need technology that provides an easy way of developing rich encapsulated parts, scattered through different routes. In our opinion, React shines for this kind of job. Once we realised this, there was no going back. Netguru needed React.

Our requirements for React-Rails integration

Sprockets are not a good out-of-the-box fit for using React with Rails. Especially when you appreciate maintainability and flexibility. We needed to find a solution to easily and repeatedly set up our Rails applications. We started with a description of things that it must cover.

We came up with the following list:

it should be easy to use for Rails developers, especially with legacy code,

especially with legacy code, React components should be accessible from Rails Views, and there should be a way to pass data directly from Rails controllers,

and there should be a way to pass data directly from Rails controllers, it should support modules so we can easily grab and use any node module we want, including CSS and other assets,

so we can easily grab and use any node module we want, including CSS and other assets, it should support the ES2015 specification,

it should be possible to write integration tests for our components.

Playing with Browserify-rails

Next, we checked out the browserify-rails gem. We had node modules now, but there was no integration with React. Therefore, we moved back to React-rails to see what’s going on under the hood. It turned out that there is a nice rails helper that is responsible for rendering mock HTML tags with data attributes representing props. On the other hand, there is the react_ujs JavaScript file which, on DOMContentLoaded events, mounts React components on previously rendered mock HTML tags. A nice solution that worked out well. But the issue was that we still could not fetch CSS and other assets from our node modules easily.

Meeting Webpack

At almost the same time, we found Webpack. Since many React-based projects use it, we thought it would be a good idea to test it out. The more we dug into it, the more we were sure that Sprockets and Rails should not deal with processing ES2015 code. Also, having experience with Gulp, we knew that configuration files related to the build should not be hidden from developers. We liked Webpack for its simplicity, possibilities and wonderfully supportive community.

We found the following blog post by Justin Gordon very helpful. He talks about using React, Webpack and Rails together.

In his solution, Webpack deals with modules, ES2015 and everything else, and produces a pure Javascript bundle file. This file can be required by Sprockets in application.js . It’s fast and simple - we can use the power of node modules and handle Javascript code the way we want.

In Justin’s repository, you can find the example application. One thing that we needed to change was how we were going to use React. In the above example, we have a client app, but we want to be able to put the React component into Rails view. This way, data can be passed to the component directly from the Rails controller. This is useful for components with static data.

In summary, Webpack provides us with:

a simple setup - we only need to define the basic Webpack config and the package.json file with all the node modules,

- we only need to define the basic Webpack config and the package.json file with all the node modules, ES6 module support,

use of all syntax features from ES6, through babel-loader,

through babel-loader, an easy way to require CSS files and other assets that are provided by a specific node module,

Also, the React bundle file is loaded via sprockets, so it can be quickly tested using capybara.

Webpack has all the features we would like to have in our setup. Let’s focus on our last requirement - accessing and passing data to components in Rails views.

Integration with Rails views and more

So, we went back to React-rails and again used parts of its helper and integration code. However, we wanted to make it easily accessible both on Rails environments (in views) and in JavaScript environments (when mixing it with - say - Backbone). That’s why we added the reactComponents object and helpers:

registerComponent

getComponent

createComponent

renderComponent

You can read more about those helpers.

This way, we can work with the same setup solution on both legacy code and the new projects.

Testing

At this point, our setup was almost ready. We were just missing tests. In our opinion, the best way to test components is to write integration specs for them. Also, we had a bad time using Jest, as it’s still under development and not particularly stable. While searching for alternatives, we found the following article. After adding the Webpack config and the Karma config, our setup was ready to go.

What's next?

Some people might choose to end the story at this point, but not us. We’re lazy Ruby on Rails developers, and there’s no way that we’re going to copy/paste a bunch of files each time we want to use React with Rails. That’s the main reason we created the react_webpack_rails (check it out on GitHub) which has modified react integration and a config generator. This way, we can quickly start working with Webpack and React in Rails.

There are many more things we would like to test. We’re looking at serverside rendering and react-hot-reload (which is already talked about in Justin’s tutorial. We would love to try mixing Rails, Flux, react-router and much more.

Conclusion

There are a lot of articles about solving this kind of problem, but doing it by ourselves was a lot more fun and informative. We are sure that React is worth learning and is a trend that is worth keeping an eye on.

We know that there are plenty more ways to accomplish the same result. However, a tool is a tool. Don’t spend too much time choosing between them - the only thing that matters is that it works the way you need it to. Maybe you’ve used some other setups for your React and Rails applications? Share your ideas in the comments!