RailsConf 2017

React on Rails

React on Rails

by Jo Cranford

In the talk "React on Rails" presented by Jo Cranford at RailsConf 2017, the speaker shares the journey of migrating a Ruby on Rails application from a jQuery-based front end to a modern, React-driven user interface. The story begins with a typical Rails application that had become cluttered with untested jQuery code, which presented challenges in maintaining and scaling the application. Over time, the need for a better user experience and more efficient coding practices drove the team to adopt React and other modern JavaScript technologies.

Key Points Discussed:
- Background of the Application: The speaker introduces Colt Tram, an online application for employee engagement surveys, which initially relied on jQuery and Bootstrap for its frontend development. jQuery's ease of use allowed rapid development but led to unmanageable spaghetti code.
- Evolution of Front-End Technologies: As JavaScript evolved, new frameworks emerged, and the speaker outlines the shortcomings of jQuery in a more complex application environment, as well as the shift towards component-based architecture with React.
- Adopting React: The transition to React was motivated by its one-way data flow, virtual DOM, and the ability to incrementally introduce components without a complete overhaul of existing code. This approach was facilitated by hiring a React expert, which was crucial for a smooth transition.
- Integration with Rails: The speaker details the technical implementation, including integrating Babel for ES6 support, using Webpack for asset management, and ultimately replacing Sprockets with Webpack to allow for more advanced JavaScript coding and maintainable CSS modules.
- Testing with Jest: The team adopted Jest for unit testing their React components, which improved code quality and allowed for the introduction of new testing paradigms like shallow rendering and snapshot testing.
- Front-End Development in Practice: The use of Redux for state management, react-router for navigation, and CSS modules for styling were introduced to enhance the user experience and application performance along the way. The speaker emphasizes the benefits of functional programming principles adopted through React, resulting in cleaner and more maintainable code.
- Lessons Learned: Throughout this journey, the speaker highlights the importance of treating front-end code as a first-class citizen, fostering a culture of better coding practices, and the ongoing need for a shared component library to maintain consistency across the application.

Conclusion: The presentation concludes with reflections on the evolution of their front-end architecture and the importance of user feedback, acknowledging that while challenges remain, the transition to React has significantly improved both development processes and user interaction with the application. The speaker encourages others undergoing similar journeys to embrace modern frameworks like React while learning from their experiences.

00:00:11.660 All right, I'm going to get started. Hi everyone, I'm Jo. I'm super excited to be here.
00:00:17.640 This is my first-ever RailsConf, so that's great! I come all the way from Melbourne, Australia, and I wanted to tell you a story today. This story starts in Melbourne with a group of four engineers who founded a company called Colt Tram, which is the company I work for now.
00:00:31.470 They built an online application using Ruby on Rails to run employee engagement surveys, providing real-time analysis of the results. Today, we have around 50 people working in our product team, with 10 development teams focused on the product.
00:00:44.219 It's built with a variety of technologies. We still have that Ruby on Rails monolith, along with some Elixir and a whole heap of JavaScript. Back at the beginning, however, it was a completely different world.
00:00:55.469 Let me set the scene a little bit better so that this story makes sense. I'm going to talk about the products in the market when we started, the front-end development scene back then, the evolution that occurred in that space, and the need for change that ultimately led us to where we are today.
00:01:13.530 The product we had offered an analysis of survey responses and faced two main areas of competition. The first was consultants, who would run surveys, then spend a long time producing results in the form of PowerPoint documents or Keynotes. While these looked beautiful, they took an excessive amount of time to complete.
00:01:28.229 The other alternative included tools like Survey Monkey and Google Forms, which provided plenty of flexibility and real-time results but made it quite challenging to analyze the data – users had to do the analysis themselves.
00:01:45.180 In this competitive market, it wasn't difficult for us to create a groundbreaking front-end. We implemented real-time analysis and basic interactivity to allow users to drill down into the results. This was sufficient to outperform those generic tools and the consultants' PowerPoint presentations.
00:02:06.840 At that time, the popular tools for front-end development were jQuery and Bootstrap. It was 2011, and while it may seem a bit dated now, it was not uncommon for developers to stick with these tools. Backbone was on the scene, and Angular was starting to gain traction.
00:02:19.290 When jQuery was first introduced, it was a game changer. Its motto, 'jQuery is designed to change the way you write JavaScript,' signified its purpose to eliminate the in-line JavaScript cluttering HTML. jQuery gave developers a way to separate their JavaScript into more manageable files.
00:02:37.050 Its current guiding principle is 'write less, do more.' It was unobtrusive and easy to integrate into Rails, as it was included by default with Rails 3.1. This made it incredibly user-friendly.
00:02:54.360 Bootstrap was another significant player; Twitter had just released version 2 of Bootstrap, a library full of layout and grid components. This made column layouts accessible to everyone, enabling us to add them from a CDN or include the library file directly within the vendor folder in Rails.
00:03:16.920 Unlike many startups aiming for cutting-edge design, we simply wanted a reasonably nice UI with smooth interactions for our users, aiming to get something to market quickly. Our primary developers were back-end engineers, so having these tools that simplified front-end coding was essential.
00:03:29.700 Years passed, and we added numerous new features to our back-end such as permissions and data analysis tools. The front-end became somewhat of a means to an end and did not receive much attention. Rails also made it easy to manipulate vendor files, which is a double-edged sword; just because you can, does not mean you should.
00:03:49.950 When we changed one or two things, upgrading became a nightmare. As a result, we ended up with plenty of spaghetti code. Meanwhile, the JavaScript world was evolving.
00:04:00.840 One of the early benefits of jQuery was its standardization across various browsers. If you needed uniform behavior in Internet Explorer, Chrome, Firefox, or others, jQuery had your back. However, as browsers improved and standardized, the library became bloated. Users increasingly started browsing the web on mobile devices, demanding faster downloads, which required us to build smaller JavaScript libraries that performed better.
00:04:34.200 At this time, JavaScript was starting to become a first-class language where we had to rethink how we structured it. Testing became a priority with frameworks like Jasmine and QUnit entering the mainstream. We were still stuck with our spaghetti code, and fixing one bug often led to another one erupting elsewhere. I saw a video that truly captured the essence of this struggle, reflecting how it felt to fix one thing only to have another issue crop up.
00:05:01.660 Now, as React was emerging, we began considering this new technology. I want to discuss why we chose to adopt React, how we evolved our asset pipeline to accommodate it, and how we began building our first component.
00:05:28.800 React was open-sourced by Facebook in 2013. At first glance, it seemed like just another shiny JavaScript framework in a sea of many options. For those learning JavaScript today, the overwhelming number of choices can be paralyzing. However, React differs significantly from its counterparts.
00:05:56.370 One of the key concepts that makes React stand out is the idea of one-way data flow. Props in React only flow down from the initial state through components. Each individual component encapsulates its own props and cannot modify them, nor can it change the global state. The only way a component can make changes is through callbacks. React components serve as a representation of the UI given a specific state.
00:06:37.790 Unlike jQuery, React does not manipulate the DOM directly; it renders the representation of the UI using JSX, which can initially be off-putting since it mixes HTML with JavaScript. People have been taught to keep these separate, but over time, many find this approach much more enjoyable to work with.
00:07:29.160 JSX employs an XML-like syntax that looks like HTML and allows us to work with both standard HTML elements and custom components. Every time the state changes, React re-renders the component by maintaining a virtual DOM in memory. It compares the current version of the DOM with the previous version, only re-rendering components that need it, which results in a more performant application.
00:08:02.920 For example, if you imagine implementing a to-do list where a user enters some text and clicks the button to add it, React processes that update efficiently. When a new to-do is added, React knows to re-render the list with this new piece of data. The added benefit of React being backed by Facebook means it has resources and a community to ensure its longevity.
00:08:30.410 When considering which JavaScript framework to use, we had to weigh several factors. Our application is primarily B2B, with users in HR accessing it via desktop computers. We didn't need to worry about mobile rendering or small screens, allowing us to focus on supporting a limited range of browsers.
00:09:09.380 We decided to support IE10 and the latest versions of other browsers, which simplified our challenge. Additionally, hiring a React expert significantly aided our transition. While React is known for its server-side rendering capabilities, that wasn't a concern for us and eased our selection process.
00:09:54.020 One size does not fit all when it comes to frameworks. I am not advocating that React is the only solution; it was merely the right choice for us at that time.
00:10:05.720 Before diving into building React components, we needed to address the issue of our outdated JavaScript code. We were not even using any ES5 features, while ES6 had introduced many exciting functionalities to improve the language.
00:10:41.150 ES6 brought significant enhancements that advanced JavaScript as a first-class language. This version introduced block scoping, immutable constants, arrow functions, string interpolation, and the spread operator, all of which facilitated a more straightforward development experience.
00:11:29.680 Babel became our transpiler of choice, allowing us to incorporate these features into our codebase. By configuring Babel, we could target specific browsers, ensuring smooth operation and the necessary polyfills.
00:12:10.760 The default Rails asset pipeline uses Sprockets to process JavaScript, images, and CSS before they are delivered to the client. Sprockets includes a feature called require trees, where if you write JavaScript files that require others, it compiles and serves them as a single bundle. This method also helps prevent browser caching of old versions by updating file names each time new code is deployed.
00:12:46.760 However, Sprockets did not support transpilers like Babel, leading us to investigate JavaScript tools such as Webpack and Browserify. Since both tools are JavaScript-based, they made sense for our JavaScript-heavy environment.
00:13:51.360 Our initial steps to integrate Webpack into the Rails asset pipeline involved using a gem that ran a Node.js process alongside the Rails server. This included a gem called Ruby Node Task and a separate gem called Webpack Rails, which helped bridge the two systems. Once Webpack finished its processing, Sprockets could then bundle these files with our existing JavaScript code.
00:14:42.909 This initial setup was complex. Although not necessarily the best solution, it allowed us to commence using React. Soon after, we faced challenges with source maps from Webpack not being supported by Sprockets. This limitation restricted our ability to debug effectively because error messages lacked context.
00:15:10.900 We decided to tweak our setup. Files processed and bundled by Webpack were kept separate from legacy files handled by Sprockets. Consequently, we used two tags in the HTML, allowing us to employ source maps and enable hot reloading during development.
00:15:54.930 To integrate our React components within the page, we utilized HAML as our templating language. A method was introduced to add top-level components into the HAML template while passing state from the Ruby side easily. This allowed us to pass props as a Ruby hash into the React component.
00:16:51.690 It outputs as a div with a data attribute containing the component name and its props. Additionally, we registered all components to be used as top-level components on the page. This enabled us to mount them correctly, ensuring the right prop values were passed down when the page loaded.
00:17:40.490 Once the page loaded, our React code would initialize, giving us a fully functional React experience in Rails. We did not stop there; we began evolving our application with Jest tests, CSS modules, and moved away from Sprockets entirely.
00:18:54.380 React provided us with tools to handle more complex states with Redux. During this transition, we also introduced animations to enhance user interactions, giving feedback that the page was in the process of changing.
00:19:36.180 To facilitate animations, we explored a library called React Motion. It allowed us to animate components smoothly between states without freezing or jarring transitions. While we faced challenges with rendering PDFs and ensuring animations didn't interfere, these enhancements significantly improved the user experience.
00:20:12.120 Redux's core tenet revolves around immutable state management. We introduced Immutable.js, which encourages thinking about state in terms of returning new instances rather than modifying existing ones. This library helps prevent subtle bugs while providing a more optimized way of handling state.
00:21:05.670 Additionally, we began using record types within Immutable.js to define specific data structures for our components. As the JavaScript landscape shifts towards stricter type checking, we utilized PropTypes to define expectations for component props, which help identify potential issues during development.
00:21:47.920 Reflecting on this journey, we’ve learned a tremendous amount. The introduction of new patterns enhanced the structure of our code. React's inspiration from functional programming principles helped influence how we approach coding not only in JavaScript but also in the Ruby on Rails domain.
00:22:26.050 Despite its headaches, legacy JavaScript remains a factor in our journey. We’ve built a vast library of React components, but we haven’t yet fully addressed their reusability. Multiple components serving similar purposes have led to a lack of consistency in our CSS, despite the introduction of CSS modules.
00:23:02.210 However, we are progressing towards a shared component library, taking inspiration from companies like Lonely Planet and Atlassian, who have published living style guides. We're also experimenting with alternatives such as Elm for part of our application.
00:23:51.030 My concluding thoughts share the notion that the front-end code is now viewed as a first-class citizen. Previously, we viewed it as a messy means to an end. Today, our users notice the difference, and we hear their positive feedback.
00:24:38.900 As you each navigate your journeys, regardless of the libraries you choose to utilize, I hope our experiences with React in a Rails environment have provided valuable insights. Thank you.