10

We’re so cutting edge: How we added a React App to our Rails project at Songkick

 3 years ago
source link: https://devblog.songkick.com/were-so-cutting-edge-how-we-added-a-react-app-to-our-rails-project-at-songkick-f8a12b76491b
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

We’re so cutting edge: How we added a React App to our Rails project at Songkick

Over the past year the engineering team at Songkick has been hard at work migrating our old data centre to the Google Cloud Platform. It has been a long process and it has had it’s fair share of hiccups and issues but we have finally crossed the finish line. All this work is already starting to pay dividends. Our development process is much slicker and faster now that we don’t have to use dev VMs and constantly sync code across from our local machine. It has also meant that many in our team have had the opportunity to gain valuable skills in Dev Ops and platform architecture that we wouldn’t have normally had the chance to get. But one of the biggest benefits to the “new world” at Songkick is the ability to use and integrate modern technologies into our site/apps that before we wouldn’t have been able to do.

One of these new technologies is React.

In our web app, we primarily use Ruby/Rails with a light scattering of JavaScript (mainly for analytics events). While migrating our web frontends to the new platform we decided to give it a few upgrades. This includes updating to use Ruby 2.6 and adding Webpack as our asset bundler.

Adding Webpack meant that we could move away from our old way of bundling assets, Wake. This was built in-house years ago and has not been maintained for over 4 years. It had a lot of limitations, one of which was not being able to transpile modern JS so we couldn’t use ES6 or any modern JS frameworks. But with the introduction of Webpack and its many loaders, we are now able to use modern JS and frameworks like React. And that’s exactly what we decided to do last quarter.

A Brand New Service

We wanted to build a presales tool that would give artists the ability to run a presale campaign on our platform that advertised an upcoming concert or tour and gave all their followers the opportunity to purchase tickets and go to their shows.

To do this we had to create a new presales service and build out functionality in our web frontends to facilitate the new presales functionality. While we did work on the songkick.com and accounts.songkick.com sites, I will be talking about the new tool we introduced to Tourbox (tourbox.songkick.com), our event listings management tool for artists and artist managers. As part of the team quarter objective, we wanted to build a tool in Tourbox that would allow artists to create a presale campaign, with all the relevant details, an image, events and ticket links, and save as a draft or publish the campaign.

Once the campaign is published all the Songkick users who track the artist will be sent an email giving them the details of the presale and a special code. We wanted the artists to see what the fans are going to receive, so we decided to use React for a live email preview.

Adding our first React component

With the recent releases of Rails you get Webpack out of the box and you have the ability to configure it to be used with React with just a simple CLI flag with creating a new rails project. By doing this you get some really useful view helper methods that allow you to put a React component in an ERB file and pass the data to that method that will get passed to the component by props, similar to locals when rendering a partial in Rails.

But as Tourbox uses an older version of Rails and is an existing project that has a lot of legacy code we didn’t have the luxury of being able to use these features so we decided to build something similar ourselves.

We had to configure Webpack to meet our needs when it came to asset bundling as we were not using the rails asset pipeline as it was especially intended to be used. As part of this configuration we had a lot of entry points when it came to bundling all our JS files so instead of bundling up all our assets in to a single big bundle, we split them up so we can choose to include them on a page if they are needed. This means that we don’t include unused JS or CSS on the page. This being the case, I decided to add a new entry point to Webpack to bundle all the React code and dependencies into a separate bundle to be included on the pages that will use React.

Image for post
Image for post
./webpack.base.config.js

So when Webpack bundles up the PresaleCampaignForm React app and all its dependencies we get a nice neat JS bundle that we can add to a page. This being react it has a plethora of dependencies so the bundle comes out being about 5MB in size which is hefty so being able to only include this on the pages that need it reduces the amount of assets the page has to download that could slow down the overall load time of a page.

Once this was done, it was as simple as using a Rails helper method to include the bundle on the presale’s /new.html.erb and /edit.html.erb files:

Image for post
Image for post
The assets.include_js is a method exposed in our in assets management gem

Now we were all set to get React to do its magic.

For this to happen we needed an element on the DOM which react could mount its virtual DOM to. In all the React tutorials it’s usually a <div id=”root”></div> element but we had to do something different. The above element is great for a SPA React app which only has a single bundle and a single mount point, but as we were using a mini react app inside a much bigger Rails app, we decided to add a little rails partial which could be reused in multiple places in the Rails app if needed. I came up with this:

Image for post
Image for post
./_react_component.html.erb

Good old Rails!
As you can see, there are a few things going on here:
1. We added a <noscript> just in case a user doesn’t have JavaScript enabled on the browser.
2. The id="<%= react_component[:component_id] %>" is a way for us to specify which react component to mount to this div
3. The data-props="<%= react_component[:props] %>" is a way for us to attach data to the div so that React can access it and pass it down to our component as props.

Once this was added we could then ask Rails to render this partial in the pages we wanted our react component to be. To do this we added a handy view helper method to our ApplicationHelper module:

Image for post
Image for post
./application_helper.rb

And used it in our view render the partial:

Image for post
Image for post
views/presales_campaign/new.html.erb

The object parameter that is passed into this method should either be an instance of a class that has an instance method of .to_hash(which returns a ruby hash of all the data that we want to be passed into the react component) or is a ruby hash (again with all the data that we want to be passed into the react component). This hash is then parsed to JSON and added to a data hash along with the component_name. In our case it was presale-campaign-form.

The partial is then rendered by Rails while passing the data hash to the partial. The key/value pairs in the hash are then accessible in the react_component partial as react_component[:component_id] and react_component[:props].

We did it. Now we were ready to start writing our first React component…

Putting all this to good use

We had done all the set up so it was time to take it for a test drive. The first step was to write a simple form that would render and take user input and be able to submit form data to our Rails controller so we could send data to our Presales service in order to save a presale.

All react apps start with an index.js file which holds the code for mounting the virtual DOM and rendering our react code:

Image for post
Image for post
react/presalesCampaign/index.js

This is where we query the DOM for an element with the id of presale-campaign-form . We then do a check to see if we found anything. If so we then parse the JSON so we can pass it down into our PresaleCampaignForm component as props.

Finally, using ReactDOM we mount and render our component (with our data being passed down as props) to our DOM container element. And there we go. We had a react component rendering in our Rails app.

Once we could render a react component on the page we needed to build out the form the artists or artist manager would fill out to create a new presale campaign. We needed a form with a few input fields for the presale details including start and end date/time, timezone, presale code and image. This was easy enough and soon enough we had a React component form. Next we added a component that allowed the user to select a number of the artist’s upcoming events to be part of the presale campaign. Once selected, they could add links to the ticketing site that would be selling the presale tickets.

We now needed a way to save the presale information to the server once the user had submitted the form. This was a bit trickier as the form was a react form, while the logic to save/update a presale was done in the Rails part of the app. We were running into problems where the Rails controller would not allow a form to be submitted that wasn’t correctly authenticated, the controller was rejecting the submitting and giving an error. To solve this issue we took the <form> element wrapper out of the PresaleCampaignForm component and use the Rails view helper method form_tag. By doing this Rails will wrap the react component in a <form> tag and also render a few hidden <input> tags that have the authentication token need by Rails to successful submit the form data to the controller:

Image for post
Image for post
views/presales_campaign/new.html.erb

The final, and most React-y, step was to add an email preview component that would be a representation of what recipient of a presale email would see when viewing it on their phone. This component is updated in real time as the user adds presale information to the form. The user is able to independently scroll the preview and click through to each ticketing site they had listed.

With that the user was able to create a new presale campaign form, add the relevant details including a picture, events and ticket links and either save the presale as a draft or submit for review. We had successfully added our first React components to Tourbox. We are now cutting edge…

This was by no means the only work we did on presales during the quarter. We built out a new presales service complete with a database and email schedulers and senders. A lot of work went into the initial MVP of the Songkick Presales and since its first successful campaign went live 3 months ago we have continued to improve the feature as a result of lots of user feedback. The Presales has been a successful product and we’ve had lots of interest from artists since it’s initial release.

So if you are an artist or artist manager interested in using our new Presales tool, head totourbox.songkick.com and signup to check it out!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK