<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[ShakaCode - Medium]]></title>
        <description><![CDATA[Articles on React, React-Native, Webpack, Ruby on Rails, startups - Medium]]></description>
        <link>https://blog.shakacode.com?source=rss----dbc83ae6fe51---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>ShakaCode - Medium</title>
            <link>https://blog.shakacode.com?source=rss----dbc83ae6fe51---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 15 Apr 2026 22:04:38 GMT</lastBuildDate>
        <atom:link href="https://blog.shakacode.com/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Clubhouse (Jira/Trello/Github) Toggl Time and Task Tracking]]></title>
            <link>https://blog.shakacode.com/clubhouse-jira-trello-github-toggl-time-and-task-tracking-438d084417a7?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/438d084417a7</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[time-management]]></category>
            <category><![CDATA[project-management]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[task-management]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Thu, 12 Mar 2020 21:34:33 GMT</pubDate>
            <atom:updated>2020-03-12T21:34:33.160Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*saPMfaw0zqVkeW8h.png" /></figure><h3>Introduction</h3><p>My number one goal as CEO of ShakaCode is that my clients are satisfied to the point they are referenceable. Since the majority of our projects are billed per hour, clear and regular communications regarding time spent on various tasks are critical to having good client relationships. Every week, I send my team and clients 3 reports that show various breakdowns that detail how time was spent. With these reports, our clients can assess the overall level of effort for various tasks and efficiency of ShakaCode development efforts. Beyond just tracking time to a task, we try to break the work up behind a task into more detailed “time entries” that can provide color to what was done.</p><p>For our clients that use an agile project management tool, like Clubhouse or Jira, it’s useful to know how much time was spent on various stories and epics. Why?</p><ol><li>Such data can help for future estimations of story points and required resources.</li><li>Such data shows where time was spent and how it correlates to delivered work.</li><li>Such data can help with the evaluation of developer effectiveness.</li></ol><p>ShakaCode’s consulting clients appreciate the transparency of having weekly and monthly reports which show a breakdown by:</p><ol><li><strong>Project — Task</strong> — Breaks down time spent on epics and stories.</li><li><strong>User — Task</strong> — Shows how each time each user spent on each story.</li><li><strong>User — Time Entry</strong> — Shows how much time each User spent on each part of every story, such as writing a test for a story, can show details for why a story took extra long.</li><li><strong>Weekly Report Grid</strong> — Shows the day of the week across columns and the users on rows, with breakdowns by project, which provides high-level details on what a developer did for each of the past 7 days.</li></ol><p>You can see samples of these reports further down in this document</p><h3>Thanks</h3><p>If you are looking for expertise in projects involving React and Ruby on Rails, possibly with server-side-rendering, ShakaCode is taking on new projects. All of our clients are technical experts that have found us mainly via our open-source efforts, especially <a href="https://github.com/shakacode/react_on_rails">https://github.com/shakacode/react_on_rails</a>. We help some clients that have a CTO and don’t want to hire additional staff. In other cases, we work side-by-side with an existing team to accelerate projects without adding full-time staff or rushing hiring.</p><p>Special thanks to the team at Jilt.com. From our work with Jilt, we got to know of Clubhouse and developed the techniques presented here. If you’re thinking of trying Clubhouse, check out some details on their referral program and consider using me as your referral with <a href="http://r.clbh.se/mvfoNeH">this link</a>.</p><p>I welcome your feedback. Feel free to email me at <a href="mailto:justin@shakacode.com">justin@shakacode.com</a>.</p><h3>Toggl Background</h3><p>ShakaCode uses the <a href="https://toggl.com/">Toggl</a> time tracking system mainly for ease of use and good reporting. Toggl tracks time spent based on 3 levels:</p><ol><li><strong>Time Entry: </strong>Freeform editing field. This article describes what should be placed here, based on the task chosen.</li><li><strong>Task</strong>: Tasks roughly map to a Clubhouse story, Github Issue, etc. Tasks require setup in the Toggl web UI. When a task is completed, it is marked as done and then it does not show in the autocomplete for time entries.</li><li><strong>Project:</strong> Each task belongs to a single Project, which is a collection of tasks. Thus, picking a task also picks the project.</li></ol><p>Toggl provides <strong>summarizing reports</strong> that group on <strong>2 levels</strong>, such as by Project-Task by User-Task, and by User-Time Entry. The reporting does not allow grouping by Task-Time Entry. Thus, we try to enter the freeform Time Entries so that they make sense without the task name for the summary reports.</p><h3>Task Definitions Come from Stories/Cards/Issues</h3><p>Different project management systems use different terminology.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*VqbnPzJQLz2c32PX.png" /></figure><ul><li><strong>Clubhouse</strong> stories: CH123</li><li><strong>Trello</strong> cards have an id, so we can use T123. Many chrome plugins show the ids.</li><li><strong>Github</strong> issues have an id: GH123</li><li><strong>Jira </strong>stories have an id: XYZ-123</li></ul><p>We’ll use “story” for the rest of this article, as well as using an example of Clubhouse with stories and ids like CH123.</p><p>In all cases, the project management stories (cards, issues, etc.) map to:</p><ul><li>Toggl Tasks</li><li>Usually, pull requests or some other work output</li></ul><p>This allows us to map time back to the intention, which is the story, as well as the result, which is usually the PR.</p><h3>Stories Map to Toggl tasks</h3><p>We map stories to toggl tasks. More specifically, we create two Toggl tasks per story, a base tasks and a tasks for reviews of the story.</p><h3>Why track the Toggl tasks to stories?</h3><ol><li>Provides a detailed placeholder for where time is spent</li><li>Allows us to revisit the Clubhouse stories to see if the point estimation of difficulty is reflected in the task description.</li></ol><h3>Why track time spent in review separate from development?</h3><ul><li>We want to make sure that a sufficient amount of time is spent on big, tough PRs. Not doing enough code review is bad!</li><li>An excessive amount of time spent during reviews might indicate:</li><li>Problems with the initial story definition</li><li>Problems with the initial code quality</li><li>A tough task</li></ul><h3>We considered tracking time spent writing tests…</h3><ul><li>Pro: Visibility in the effort to create the tests</li><li>Con: If doing TDD, one is bouncing back and forth between implementation, tests, refactoring, etc.</li></ul><p><strong>Recommendation</strong>: Provide some visibility in the <strong>Time Entry </strong>(not the task title)</p><h3>Time Entries to Better Explain Time Spent on Tasks</h3><p>The time entry in Toggl is a freeform text entry associated with the time tracking to a task. Often, a developer will copy the task definition into the time entry, as the time entries are never shown on the same <strong><em>summary </em></strong>reports with the tasks. Thus, a time entry like “Debugging” should never be used as it’s confusing as to what task it had mapped to.</p><p>For larger “tasks,” we recommend prefixing the time entry with the story ID, like “<strong>CH123 — </strong>“ so that the time entry might look something like this. This provides the ShakaCode client with additional details on where time was spent in completing a longer task. <strong>Such time entries for a larger task should typically be less than 3 hours</strong>, so as to provide sufficient explanation of time spent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*mgSDpGr5fXLsQmK3.png" /></figure><h3>Epics May Map to Toggl Projects</h3><p>Toggl allows us to group tasks into “projects.” Larger epics in Clubhouse can roughly map to projects. Since all stories map to epics, it’s not necessary to have the epic name and Epic ID in the task name.</p><h3>Task Setup in Toggl</h3><h3>Clubhouse Tasks, Dev and Review</h3><p>The task names are of this format, mirroring the Clubhouse story:</p><ul><li><strong>CH123 — Story Title</strong></li><li>Development including writing tests.</li><li><strong>CH123 Review — Story Title</strong></li><li>Time spent by the reviewers</li></ul><h3>Why have a review task?</h3><p>Having a separate review task allows tracking the amount of time spent in review.</p><p>It is important to set up <strong>both </strong>(with and without “Review”)** **Toggl tasks at the beginning of working on the story. It’s a bit awkward to have to add the review task later.</p><h3>Generic Tasks</h3><p>For every project, we set up the following generic tasks that are used when the work does not correspond to a story specific task.</p><ul><li><strong>Ask</strong></li><li>Probably needs a task, but one is not yet created</li><li><strong>Bug Investigation</strong></li><li><strong>Other Development Tasks</strong></li><li>For time entries that don’t justify a big enough grouping to be a “Task”. This is a judgment call.</li><li><strong>Other Code Reviews</strong></li><li>Non-categorized code review. Prefer categorized ones.</li><li><strong>Other Design</strong></li><li>Non-categorized design. Prefer categorized ones.</li><li><strong>Other Meetings</strong></li><li>Non-categorized meeting. Prefer categorized ones.</li><li><strong>Performance Investigation</strong></li><li><strong>Ideally, create a story first for the performance work</strong></li><li><strong>Project management</strong></li></ul><p>We prefer non-misc, specific tasks where possible. In other words, tracking time to an anonymous task “Misc” is an antipattern.</p><h3>Reporting</h3><p>The goal of the setup is to provide useful reporting.</p><h3>Reporting by Project and Tasks</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*GTNJ1CeX1n-lIBD7.png" /></figure><h3>Reporting by User and Tasks</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*Z5WLP-IY5TenLGIP.png" /></figure><h3>Reporting by User and Time Entry</h3><p>When a developer starts work on a task, the developer can copy the task name into the <strong>Time Entry <em>and </em></strong>change the information as needed to provide any additional color on how the time was used, such as debugging something difficult, writing tests, etc.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*4jcmuP3DV0JM_kx5.png" /></figure><h3>Reporting by the Days of the Week</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*ZxG2ChXkzA_KEoE7.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=438d084417a7" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/clubhouse-jira-trello-github-toggl-time-and-task-tracking-438d084417a7">Clubhouse (Jira/Trello/Github) Toggl Time and Task Tracking</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimizing Google Fonts on Gatsby Sites]]></title>
            <link>https://blog.shakacode.com/optimizing-google-fonts-on-gatsby-sites-5fb9fb86be1c?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/5fb9fb86be1c</guid>
            <category><![CDATA[fonts]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[google-fonts]]></category>
            <category><![CDATA[gatsbyjs]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Thu, 12 Mar 2020 21:30:37 GMT</pubDate>
            <atom:updated>2020-03-12T21:30:37.146Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1007/0*tUrr_c95riA2PRkp.png" /></figure><h3>TLDR:</h3><ul><li>Don’t use an @import url for google fonts!</li><li>Use the gatsby-plugin-prefetch-google-fonts plugin</li><li>Go through this tutorial: on <a href="https://web.dev/codelab-preload-critical-assets/">Preload critical assets to improve loading speed</a>.</li></ul><h3>Backstory</h3><p>We recently built our new ShakaCode.com website using Gatsby.</p><p>I noticed that the fonts jumped around a lot. <em>And I hated that!</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HLJM_kw79v_NwN0-.gif" /></figure><p>While doing some work to update <a href="https://github.com/shakacode/react_on_rails">React on Rails</a> for <a href="https://loadable-components.com/">Loadable-Components</a>, I was going through this excellent tutorial on <a href="https://web.dev/codelab-preload-critical-assets/">Preload critical assets to improve loading speed</a>. Part of the tutorial included some experimentation with fonts and preloading.</p><p><strong>Aha!</strong> There had to be a problem with the HTML generated for the ShakaCode home page. I bet it doesn’t preload! Sure enough, it wasn’t! I verified that by searching the page source for the font “Montserrat,” which was buried inside a mass of inlined CSS. Yep, no preload!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*nawGyPKUoyiJ9aXx.png" /></figure><p>I searched the codebase for this font, and I found it inside of a styled-components CSS-in-JS file.</p><h3>Don’t use @import url for google fonts!</h3><p>I searched the codebase and found that Montserrat was loaded using the CSS @import rule.</p><pre>import { createGlobalStyle } from &quot;styled-components&quot;</pre><pre>const GlobalStyle = createGlobalStyle`<br>  @import url(&#39;https://fonts.googleapis.com/css?family=Montserrat:600,800,900|Open+Sans:400,400i,600&amp;display=swap&#39;);</pre><p>Using @import to load Google fonts was exactly what should not have been done. Many search results on this topic pointed to exactly what I observed in the Chrome Dev Tools profiler: &quot;@import&quot; will defer the loading of the resource and slow down the page.</p><p>I looked at the performance of loading the fonts on the current live site. In the web.dev tutorial I just mentioned, I got a better understanding of how to use the Chrome Dev Tools <strong>Network</strong> tab a bit better. To get some better clarity around a slow network, I throttled the network speed just a bit to Fast 3G.</p><p>OMG! Of course, the page jumps! The Montserrat font was not even queued until 4.1s!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*q-6v0VblBNA2E1JX.png" /></figure><h3>Gatsby plugin gatsby-plugin-prefetch-google-fonts to the rescue!</h3><p>Next, I googled around for the topic of how best to apply Google fonts to a Gatsby site.</p><p>Ahh, of course, there was a Gatsby plugin for this issue: <a href="https://www.gatsbyjs.org/packages/gatsby-plugin-prefetch-google-fonts/?=gatsby-plugin-prefetch-google-fonts">gatsby-plugin-prefetch-google-fonts</a>. I just had to add the plugin and remove the old font code. Note, the display=swap is automatically set by the plugin. While not documented, I did a quick <a href="https://github.com/escaladesports/gatsby-plugin-prefetch-google-fonts/search?q=swap&amp;unscoped_q=swap">search for <strong>swap</strong> on the github repo</a>.</p><p>The resulting page source shows the preloads.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/0*RSR_uGL4EiMJjLGq.png" /></figure><p>Now, all the Google fonts load right at the beginning of the page load.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*H6w1mssbyLzyWoy3.png" /></figure><p>Here’s the diff of my pull request to the ShakaCode.com source.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*3FI9PQzr894-apDD.png" /></figure><p>I hope you found this useful!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5fb9fb86be1c" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/optimizing-google-fonts-on-gatsby-sites-5fb9fb86be1c">Optimizing Google Fonts on Gatsby Sites</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Easy React Server Rendering with rails/webpacker v4 and React on Rails]]></title>
            <link>https://blog.shakacode.com/easy-react-server-rendering-with-rails-webpacker-v4-and-react-on-rails-71602276cf4c?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/71602276cf4c</guid>
            <category><![CDATA[react-on-rails]]></category>
            <category><![CDATA[rails]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[babel]]></category>
            <category><![CDATA[webpack]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Wed, 17 Oct 2018 06:15:08 GMT</pubDate>
            <atom:updated>2018-10-17T06:14:25.780Z</atom:updated>
            <content:encoded><![CDATA[<p>I’m excited about the v4 update of Webpacker. This release brings several big updates from the Webpack ecosystem, notably support for Webpack v4 and Babel 7.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OMJsZbKQWOSEqYeqanp4qg.png" /></figure><p>In case you haven’t hard, you want to be on Webpack v4! Why? For the official story, see the <a href="https://medium.com/webpack/webpack-4-released-today-6cdb994702d4">official release article</a>. To summarize:</p><ol><li>Much faster build times, so you can see your changes more quickly!</li><li>Easier configuration, although if you’re using rails/webpacker, you might not see that so much, since you only are customizing beyond the defaults set by rails/webpacker.</li><li>Better support for code-splitting. If you’re using react-router , you can get a solid performance gain by code-splitting your routes.</li></ol><p>While Webpack v4 has been out since February 2018, rails/webpacker has not yet been officially updated.</p><p>As of October 14, 2018, I just tested out the pre-release version of <a href="https://github.com/rails/webpacker">rails/webpacker</a>, and <strong>it works fine with </strong><a href="https://github.com/shakacode/react_on_rails"><strong>React on Rails</strong></a>. See the details at the bottom here.</p><p>Additionally, I just published React on Rails version 11.1.7, which fixes an issue with server-side-rendering when using the webpack-dev-server, which optionally provides Hot Module Reloading.</p><p>In case you want to see how easy it is to set up a live web application leveraging Rails plus React, you really should give React on Rails a try. The React on Rails generator leverages rails/webpacker to enable a zero-config setup of your client-side assets.</p><h3>Why Use rails/webpacker for Webpack setup?</h3><p>React on Rails has utilized rails/webpacker since September 2017 for the view helpers and, optionally, for the Webpack configuration. The generator and tutorial utilize the automatic Webpack configuration because it’s awesome for a quick demo. However, many React on Rails applications needing server rendering should consider a custom Webpack setup, as explained below.</p><h3>Why Have a Custom Webpack Setup?</h3><p>The main issues I’ve seen with using rails/webpacker for the Webpack configuration are:</p><ol><li>Do you want the extra layer of abstraction on top of the simplified setup of Webpack v4? <a href="https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a">Webpack v4 introduced the concept of “modes”</a>. The magic can have its downsides. Not only must you consult the well-written Webpack docs, but you might need to dig into the source code of rails/webpacker to see what it’s doing.</li><li>rails/webpacker does not support different configurations for server and client rendering. This is recommended (and probably necessary) if you are using server rendering and you need to have different configurations for client and server rendering, such as different entry points. For example, the code for react-router on the client must be different than for server rendering.</li></ol><p>My company, <a href="https://www.shakacode.com">ShakaCode</a>, has helped many companies with their Webpack and overall React server-side rendering setup for efficient development and optimized deployments.</p><h4>Creating a new React on Rails App to Use webpacker v4</h4><p>I just updated the <a href="https://github.com/shakacode/react_on_rails/blob/master/docs/tutorial.md#using-a-pre-release-of-railswebpacker">React on Rails tutorial instructions</a> to include the details of how to use the pre-release version of rails/webpacker. You can find the <a href="https://github.com/shakacode/react_on_rails/blob/master/docs/tutorial.md#using-a-pre-release-of-railswebpacker">details here</a>. You can see the basic steps followed here in this <a href="https://github.com/shakacode/test-react-on-rails-plus-webpacker-v4">GitHub repo</a>.</p><h4>Upgrading an Existing React on Rails App to Use rails/webpacker v4</h4><p>The following steps can be followed to update a Webpacker v3.5 app to v4 based on Github’s rails/webpacker master branch. Here is an <a href="https://github.com/shakacode/react_on_rails-tutorial-v11/pull/1/files">example commit of these changes</a>. Here is a list of the steps.</p><ol><li>Update the Gemfile’s webpacker to <strong>gem ‘webpacker’, github: “rails/webpacker&quot;</strong></li><li>Update the package.json’s @rails/webpacker to <strong>@rails/webpacker”: “rails/webpacker”</strong>. Note, this is how you reference the github version.</li><li>Merge changes from the new the new rails/webpacker default <a href="https://github.com/rails/webpacker/blob/4a5fac9bdd662645c254c419a4363240acb54239/lib/install/config/.babelrc">.babelrc</a> to your /.babelrc. If you are using React, you need to add &quot;@babel/preset-react&quot;, to the list of presets.</li><li>Copy the file <a href="https://github.com/rails/webpacker/blob/4a5fac9bdd662645c254c419a4363240acb54239/lib/install/config/.browserslistrc">.browserslistrc</a> to /.</li><li>Merge any differences between the new rails/webpacker <a href="https://github.com/rails/webpacker/blob/4a5fac9bdd662645c254c419a4363240acb54239/lib/install/config/webpacker.yml">config/webpacker.yml</a> and your /config/webpacker.yml.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=71602276cf4c" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/easy-react-server-rendering-with-rails-webpacker-v4-and-react-on-rails-71602276cf4c">Easy React Server Rendering with rails/webpacker v4 and React on Rails</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[HVMN’s 90% Reduction in Server Response Time from React on Rails Pro]]></title>
            <link>https://blog.shakacode.com/hvmns-90-reduction-in-server-response-time-from-react-on-rails-pro-eb08226687db?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/eb08226687db</guid>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[react-on-rails]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Thu, 13 Sep 2018 09:00:57 GMT</pubDate>
            <atom:updated>2018-10-29T00:38:20.935Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>The price we paid for the consultation + the React on Rails pro license has already been made back a couple of times from hosting fees alone. The entire process was super hands off, and our core team was able to focus on shipping new feature during that sprint.</blockquote><p><a href="https://github.com/shakacode/react_on_rails/blob/master/docs/testimonials/hvmn.md">HVMN Testimonial, Written by Paul Benigeri, October 12, 2018</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/913/1*AgGfqn_hhrq79nNXlVy5dQ.png" /><figcaption>HVMN.com</figcaption></figure><p><strong>Since HVMN installed React on Rails Pro, they’ve seen a roughly 90% improvement in server-response times.</strong> The gain came from a combination of intelligent caching along with a much more efficient Node React Server Rendering Engine.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*i9aVPcOMSuxGAAnshopeNA.png" /><figcaption>Scout Graph: Deployment of React on Rails Pro React Fragment Caching</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SG5QKpsRO6AdFefKmDaRqg.png" /><figcaption>Scout Graph: Deployment of React on Rails Pro Node React Server Rendering</figcaption></figure><blockquote>“I looked at the Scout data on the performance changes after the deployments of both the fragment caching and the change from switching to a standalone Node React rendering engine, and I can confirm that the performance improvements were both significant beyond any doubt.” Derek Haynes, co-founder Scout.</blockquote><h3>Background</h3><p>HVMN’s site is a Ruby on Rails app. The customer-facing side uses a single Rails view with a single React component. Routes are handled using react-router along with a Rails wildcard route. Because the site, like most e-commerce sites, depends heavily on SEO, the site server renders React on all pages. React on Rails handles integration of Rails with React. The Rails pages/index.html.hamlview contains one helper call to the React on Rails view helper react_component.</p><p><a href="https://hvmn.com">HVMN</a> has been using React on Rails since late 2015. I got to know HVMN’s head of e-commerce, <a href="https://hvmn.com/team">Paul Benigeri</a>, after he got involved in the ShakaCode slack workspace and the <a href="https://github.com/shakacode/react_on_rails">React on Rails</a> open source.</p><p>Paul reached out to me in late May 2018 to learn about how React on Rails Pro could improve the performance of HVMN’s e-commerce site, especially in regards to server rendering of React with Ruby on Rails.</p><h3>3 Performance Enhancements</h3><p>The addition of React on Rails Pro to the HVMN site resulted in reducing the server response times almost 90%. Scout reporting started with a median response time of around 1100 ms and dropped down to a median of about 120ms, an 89% improvement. New Relic showed a similar improvement of the average going from 953ms to 127ms, an 87% improvement.</p><p><strong>React on Rails Pro</strong> offers 3 types of performance enhancements over the open source React on Rails. These performance enhancements were added sequentially to identify the impact of each.</p><h4>1. Pre-Render Caching</h4><p>This cache intercepts the server rendering request such that two requests with the same parameters will not result in JavaScript execution a second time. Of course, many factors come into play with the cache, including any changes in the JavaScript source files.</p><p>Pre-render caching<strong> </strong>provided a slight impact of from 2–5%, per New Relic and Scout data. However, the improvement was too small to be conclusive.</p><h4>2. Fragment Caching of React Server Rendering</h4><p>This type of caching is analogous to the Rails fragment cache view helper. The difference is that the React on Rails caching API is specific to rendering a react component. The programmer needs to consider cache keys in exactly the same manner as other fragment caches for Rails. However, in the case of React components, the cache key needs to be optimized based only on the props for rendering. The React on Rails Pro library handles all the other nuances of the cache key, including a determination if any serializers for the props have changed. The API is structured such that the calculation of props is placed in a block so that creating the props is not done if the cache key exists. the site Creating the props typically involves database queries and many string manipulations to convert the data into a JSON string.</p><p><strong>Fragment Caching made the biggest difference in overall response times</strong>. Measuring the 3 days before and after fragment caching was added, Scout reported a <strong>59% improvement in the median response time</strong> for the site’s main controller action (PagesController#index), from 943ms to 382ms. Similarly, New Relic reported the average execution time going from 953ms to 392ms, a 59% improvement.</p><h4><strong>3. Node React Server Rendering rather than Ruby Embedded JavaScript</strong></h4><p>I had suspected performance issues from using an embedded JavaScript VM inside of the Ruby VM. One thing that is for sure is that if there are any memory leaks in the JavaScript code from repeatedly running server rendering code. The React on Rails Pro Node Renderer utilizes a standalone Node server using a recent version of Node.js. A big advantage of standalone Node is that we can use proper Node tooling analyze performance and track down memory leaks.</p><p>React on Rails Pro <strong>Node React Server Rendering</strong> provided a healthy boost in performance. Measuring the 3 days before and after the rendering engine change, Scout reported a <strong>69% drop in the median response time</strong>, going from 387ms to 120ms. New Relic reported a similar gain of 68% drop in the average response time.</p><h3>Implementation</h3><p>You might be wondering if it was difficult to achieve these gains. Installation of React on Rails Pro included installing the gem, turning on the pre-render cache and configuring the Node React Server Renderer. These steps required only configuration, rather than programming.</p><p>The enablement of React fragment caching required the same level of detail of any Rails fragment caching. The main steps were to identify efficient cache keys and to ensure that all props were fetched in the block passed to the React on Rails Pro view helper cached_react_component.</p><h3>Contact Information</h3><p>For additional details and confirmation of these results, feel free to email:</p><ul><li>Paul Benigeri, HVMN’s E-Commerce Lead, <a href="mailto:paul@hvmn.com">paul@hvmn.com</a>. Paul wrote this: <a href="https://github.com/shakacode/react_on_rails/blob/master/docs/testimonials/hvmn.md">HVMN Testimonial, Written by Paul Benigeri, October 12, 2018</a></li><li>Derek Haynes, Scout co-founder, <a href="mailto:support@scoutapp.com">support@scoutapp.com</a></li><li>Justin Gordon, ShakaCode CEO, <a href="mailto:justin@shakacode.com">justin@shakacode.com</a></li></ul><p>If you’re interested in trying out React on Rails Pro, <a href="emailto:justin@shakacode.com">please email Justin</a>. You can find the documentation of React on Rails Pro <a href="https://github.com/shakacode/react_on_rails/wiki">here</a>.</p><h3>Comparing Scout vs. New Relic</h3><p>The below screen grabs support the data above. I dug heavily into the available tools from New Relic and Scout. One thing I really liked about Scout was the ability to have a graph compare 2 periods. I show that in the graphs below. I couldn’t find any such feature from New Relic. One thing I did like about New Relic was that I could get data older than 30 days. Scout is currently limited to 30 days of historical data.</p><h4>Scout Data</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O5kHxvDzMWdF9z11GGgv1Q.png" /><figcaption>Scout profiling showing gains from React fragment caching</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gJkbfT_2oyJB_asxd93DPg.png" /><figcaption>Scout profiling showing gains from the Node React Server Renderer</figcaption></figure><h4>New Relic Data</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/798/1*p6CXy3UU2QZAFOICrsQqlQ.png" /><figcaption>New Relic showing the improvement of adding React on Rails Pro Node React Server Rendering</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/618/0*cIFsItxwWtiY_gOz" /><figcaption>New Relic showing before fragment caching, after fragment caching, and after adding the Node React Renderer.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eb08226687db" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/hvmns-90-reduction-in-server-response-time-from-react-on-rails-pro-eb08226687db">HVMN’s 90% Reduction in Server Response Time from React on Rails Pro</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Almost Fell for Phishing!]]></title>
            <link>https://blog.shakacode.com/how-i-almost-fell-for-phishing-8413637a3602?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/8413637a3602</guid>
            <category><![CDATA[hacking]]></category>
            <category><![CDATA[phishing]]></category>
            <category><![CDATA[passwords]]></category>
            <category><![CDATA[security]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Thu, 05 Apr 2018 02:21:18 GMT</pubDate>
            <atom:updated>2018-04-05T02:39:29.217Z</atom:updated>
            <content:encoded><![CDATA[<p>I take some pride in being “tech savy” enough that I would never fall for phishing.</p><p>However, it <em>almost</em> happened to me today! <strong>I’m sharing what happened so that others can avoid this issue.</strong></p><p>I got this message in my company’s help desk (Intercom) on <a href="https://www.hawaiichee.com">hawaiichee.com</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/1*mkKl14Oevgtz2w2xITWMGg.png" /></figure><p>We have a very active Facebook media effort for our page: <a href="https://facebook.com/HawaiiChee">facebook.com/HawaiiChee</a>. We’re partnering with many content creators for content, so the message was <strong>very</strong> <strong>plausible</strong>.</p><p>What made the phishing attempt realistic?</p><ol><li><strong>The URL provided in the main call-to-action link went to the official Facebook site. </strong>That was probably the only part of the email that I read super-carefully. Normally, a slightly misspelled URL is a tip-off to a scam site.</li><li>There were no other typos in the email. So, the first part of the phishing attempt worked. It got me to click on the URL. Normally, that’s a pretty bad mistake already, but I <em>knew</em> I was going to the <strong>official Facebook site</strong>, so how bad can that be?</li></ol><p>I skimmed very quickly the content on the left side of the Facebook page. HTTPS to Facebook. Must be legit, right?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/755/1*GCDDSpdXDEh7KL3qyVE9_A.png" /></figure><p>Nothing jumped out at me, but, to be honest, my skimming was quick enough that I started to fill out the form.</p><p>I stopped just short of putting in my Facebook password. <em>Why would Facebook be asking for my password again?</em> This did not make sense. Wait, and what about this grammar error “We made abble this form for”?</p><p><strong>WAIT!</strong></p><p><strong>WHAT!</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/755/1*WByK8POVZiRxtgST-uqcUg.png" /></figure><p>Heart racing, I double checked again. It’s the real FB site. What is going on?</p><p>Hey, there are more typos on this form. There weren’t, however, any on the email. I guess the hackers only spell and grammar check emails!</p><p><strong>BINGO! This is a SCAM!</strong></p><p>I noticed the “From” did have a typo in the domain name: “<strong>noreply@facbooksupport.com</strong>.” Notice, there’s no “e” in the “facebook”!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/619/1*7klnYXB1wUwv8zUKptcY_w.png" /></figure><p>HOLY !*#!</p><p>I was on the verge of putting in my FB password!</p><p>I went back and double checked the email. Yes, all real Facebook links. <strong>The ONLY surefire clue on the email was the misspelled “From” domain name</strong>. I bet that is why Google threw this in my spam folder originally.</p><p>I forwarded the email to <a href="mailto:phish@fb.com">phish@fb.com</a>. However, I didn’t get any reply. I hope they track the scammers down!</p><p>And today, I got the same hack attempt again! But no stress today.</p><h3>Tips for You to Avoid Getting Hacked</h3><p>I hope this article might help you avoid getting hacked. The most essential bits of advice I can give you are:</p><ol><li>Two Factor Authentication (2FA) for sites that offer it, like Google, Facebook, Github, etc.</li><li>Use a password manager like LastPass.com, 1Password.com</li><li>Double and triple check from email address domains and links, and don’t click on links unless you’re sure they are legit.</li><li>Scammers for some reason don’t spell and grammar check, so look out for that!</li></ol><p>If this article helped you, please consider how you can help me:</p><ul><li>Check out <a href="https://www.hawaiichee.com">hawaiichee.com</a> if you’re considering looking for a vacation rental in Hawaii.</li><li>Check out my company <a href="http://www.shakacode.com">ShakaCode</a> if you’d like my help with your web application development, be it a new project or help for your team, especially if you’re using Ruby on Rails plus React. I’m the creator of <a href="https://github.com/shakacode/react_on_rails">https://github.com/shakacode/react_on_rails</a>.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8413637a3602" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/how-i-almost-fell-for-phishing-8413637a3602">How I Almost Fell for Phishing!</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ReasonML: Eliminating illegal state]]></title>
            <link>https://blog.shakacode.com/reasonml-eliminating-illegal-state-cfc3811857de?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/cfc3811857de</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[reason]]></category>
            <category><![CDATA[bucklescript]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[reasonml]]></category>
            <dc:creator><![CDATA[Alex Fedoseev]]></dc:creator>
            <pubDate>Fri, 23 Mar 2018 12:22:49 GMT</pubDate>
            <atom:updated>2018-03-23T12:23:09.591Z</atom:updated>
            <content:encoded><![CDATA[<p>Next thing I’d like to share is how <a href="https://reasonml.github.io/">ReasonML</a> helps in making illegal states unrepresentable in our apps.</p><p>Here’s the common pattern of shaping a state in JS apps:</p><pre>type State = {|<br>  loading: boolean,<br>  data: Data | null,<br>  error: Error | null,<br>|};</pre><p>What’s wrong with this? Let’s see how it can be handled in UI:</p><pre>render = () =&gt;<br>  &lt;div&gt;<br>    {this.state.loading &amp;&amp; &lt;Spinner /&gt;}<br>    {!this.state.loading &amp;&amp;<br>      !this.state.error &amp;&amp;<br>      &lt;div&gt;{this.state.data.foo}&lt;/div&gt;<br>    }<br>    {this.state.error &amp;&amp; &lt;div&gt;{this.state.error.message}&lt;/div&gt;}<br>  &lt;/div&gt;</pre><p>It can be improved a bit by re-shaping this state:</p><pre>type State = {|<br>  status: &quot;loading&quot; | &quot;ready&quot; | &quot;error&quot;,<br>  data: Data | null,<br>  error: Error | null,<br>|};<br><br>render = () =&gt; {<br>  switch (this.state.status) {<br>  case &quot;loading&quot;:<br>    return &lt;Spinner /&gt;;<br>  case &quot;ready&quot;:<br>    return &lt;div&gt;{this.state.data.foo}&lt;/div&gt;;<br>  case &quot;error&quot;:<br>    return &lt;div&gt;{this.state.error.message}&lt;/div&gt;;<br>  default:<br>    throw new Error(&quot;¯\_(ツ)_/¯&quot;);<br>  }<br>}</pre><p>But the main issue is still there: conditional dependencies between state properties. When loading === false (or status === &quot;ready&quot;) it implicitly assumes that data is not null. No guarantees tho. Opened doors into an illegal state.</p><p>When you use Flow or TypeScript, these tools warn you that data might be null and you have to add all these annoying checks to calm type system down:</p><pre>case &quot;ready&quot;:<br>  if (!this.state.data) {<br>    throw new Error(&quot;Uh oh no data&quot;);<br>  }<br>  return &lt;div&gt;{this.state.data.foo}&lt;/div&gt;;</pre><p>I look at the code above and I’m just sad.</p><h3>The light</h3><p>First of all, let me introduce you to the thing called variant.</p><pre>type status =<br>| Loading<br>| Ready<br>| Error;</pre><p>This is type similar to enum in TS except its parts are not strings (nor any other data type you familiar with from JS). These things called tags (or constructors).</p><p>Now the magic moment: every tag can hold its own payload!</p><pre>type status =<br>| Loading<br>| Ready(&#39;data)<br>| Error(&#39;error);</pre><p>If you’re not there yet, here’s the code (mixing Reason &amp; JS just for clarity’s sake!):</p><pre>type Status =<br>| Loading<br>| Ready(&#39;data)<br>| Error(&#39;error);<br><br>type State = {status: Status};<br><br>class Foo extends React.Component {<br>  state = {status: Loading};<br><br>  componentDidMount = () =&gt; {<br>    api.getData()<br>      .then(data =&gt; this.setState({status: Ready(data)}))<br>      .catch(error =&gt; this.setState({status: Error(error)}));<br>  };<br><br>  render = ({state}) =&gt; (<br>    &lt;Layout&gt;<br>      {<br>        switch (state.status) {<br>        | Loading =&gt; &lt;Spinner /&gt;<br>        | Ready(data) =&gt; &lt;div&gt;{data.foo}&lt;/div&gt;<br>        | Error(error) =&gt; &lt;div&gt;{error.message}&lt;/div&gt;<br>        };<br>      }<br>    &lt;/Layout&gt;<br>  );<br>}</pre><p>How beautiful is that! There’s no way to get into an illegal state in this component. Everything is type safe. Combine it with “everything is an expression” in Reason and you can use pattern matching at any point of your JSX render tree (spot switch as a child of &lt;Layout /&gt;).</p><p>You know <a href="https://reasonml.github.io/docs/en/quickstart-javascript.html">what to do</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cfc3811857de" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/reasonml-eliminating-illegal-state-cfc3811857de">ReasonML: Eliminating illegal state</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ReasonML: Modules]]></title>
            <link>https://blog.shakacode.com/reasonml-modules-9fa50045a7ab?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/9fa50045a7ab</guid>
            <category><![CDATA[reasonml]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[bucklescript]]></category>
            <category><![CDATA[reason]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Alex Fedoseev]]></dc:creator>
            <pubDate>Tue, 13 Mar 2018 16:39:28 GMT</pubDate>
            <atom:updated>2018-03-16T03:43:47.392Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I’ve been investing quite a lot in learning ReasonML and TBH I’m pretty much dead as JS developer right now because I’ve seen the better world. Much better one.</p><p>As a part of “Selling ReasonML to my colleagues” campaign (and to anyone, really), I’m going to spam your feeds from time to time with ReasonML related write-ups (hopefully, plural!). I’m too lazy these days to do epic monolithic posts so it’s going to be almost twitter-like shout-outs about the features I’m excited about the most.</p><p>Ok, first one is definitely about <strong>modules</strong>. It seems this is the number one thing that confuses the most of newcomers from JS world (I was there!) so let’s start with it.</p><h3>Fact #1: Each .re file is a module</h3><p>Let’s say you created new file Math.re. Boom, you have a new module in your app called Math.</p><blockquote>By convention, all filenames are capitalized to match module name. You can<br> name file math.re but module name is still capitalized: Math.</blockquote><h3>Fact #2: All content of the module is exported by default</h3><p>If you create a type or a function or whatever inside your module it’s automatically available for module’s consumers using dot notation.</p><pre>/* Math.re */<br>let sum = (a, b) =&gt; a + b; </pre><pre>/* Now you can use `Math.sum` in another module */</pre><h3>Fact #3: All modules are available globally</h3><p>Let’s say you created file App.re and want to use sum function from Math. How can you import it? The answer is “You don’t need to!”. All your root modules are available everywhere in your app. You can use any of them once you need it without messing with imports.</p><pre>/* App.re */</pre><pre>let onePlusTwo = Math.sum(1, 2);</pre><p>Imagine when you implement some UI where you need Button, Input, Link etc etc: every time you need a new component in JS you have to go up, import it, go back to where you were. With Reason, you can just use whatever you want right here right now without interrupting your flow. So good! Once you’ll start using it, you’ll get how brilliant this is.</p><h3>Fact #4: No folders (for the compiler), all filenames must be unique</h3><p>Of course, you can use folders to group your files as you usually do (requires a bit of configuration) but for the compiler, all your files within a project is a flat list of modules. So all your files, no matter where they are located, must have unique names (remember, all modules are available globally). Compiler backs you up in case you accidentally created a file with a non-unique name.</p><p>At the very beginning, it might seem inconvenient constraint but in reality, it makes the naming of your modules accurate and explicit across the entire app.</p><p>E.g. in JS you can easily get into this state:</p><pre>// LoginButton.js<br>export default AuthButton extends React.Component {}</pre><pre>// LoginForm.js<br>import Button from &quot;./LoginButton&quot;;</pre><p>What a mess! If you ever decide to rename your component you have to change all these places to keep your naming accurate. Meh. In Reason world, you have only one source of truth: file name. So it’s always guaranteed accurate across the entire app.</p><p>Read more about modules in the official documentation: <a href="https://reasonml.github.io/docs/en/module.html">https://reasonml.github.io/docs/en/module.html</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9fa50045a7ab" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/reasonml-modules-9fa50045a7ab">ReasonML: Modules</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing React on Rails v9 with Webpacker Support]]></title>
            <link>https://blog.shakacode.com/introducing-react-on-rails-v9-with-webpacker-support-f2584c6c8fa4?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/f2584c6c8fa4</guid>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Mon, 11 Sep 2017 08:05:20 GMT</pubDate>
            <atom:updated>2017-09-11T08:05:01.315Z</atom:updated>
            <content:encoded><![CDATA[<p>React on Rails v9 completes the update to using <a href="https://github.com/rails/webpacker">Webpacker</a> for publishing assets to Rails views, rather than the legacy “asset pipeline.”</p><p>The integration of Webpacker solves two problems for React on Rails users:</p><ol><li>Webpacker provides standard view helpers to enable direct publishing from Webpack output to a Rails view. Previously, React on Rails apps would typically put the Webpack output into the asset pipeline. Webpack evolved to fully and better handle many of the Asset Pipeline’s responsibilities, including minification and fingerprinting.</li><li>Webpacker provides a great starter Webpack configuration. While the prior versions of the React on Rails installation generator had provided a very simple starter Webpack configuration, this was not an area of focus of React on Rails. New installations of React on Rails via the generator default to using the Webpack configuration from Webpacker.</li></ol><p>Before Webpacker v3, React on Rails could not utilize the official rails/webpacker with React on Rails. That led to the creation of <a href="https://github.com/shakacode/webpacker_lite">shakacode/webpacker_lite</a> and React on Rails v8. I documented the details of in the article <a href="https://blog.shakacode.com/webpacker-lite-why-fork-webpacker-f0a7707fac92">Webpacker Lite: Why Fork Webpacker?</a> The major benefit of this fork of Webpacker was that it allowed us to figure out the gaps in Webpacker to support a project like React on Rails. The fork led to detailed discussions resulting in a merge of webpacker_lite into webpacker. You can find the details in Webpacker <a href="https://github.com/rails/webpacker/issues/464">issue 464</a> and <a href="https://github.com/rails/webpacker/pull/601">PR 601</a>. The details are only relevant so far as to demonstrate the level of work involved in making this as simple as it is now with React on Rails V9 and Webpacker V3.</p><h3>Why use React on Rails in addition to Webpacker?</h3><p>Given that Webpacker already provides React integration, why would you add React on Rails? Additional features of React on Rails include:</p><ol><li>Server rendering, often for SEO optimization.</li><li>Direct passing of props from your Rails view to your React components rather than having your Rails view load and then make a separate request to your API.</li><li>Redux and React-Router integration</li><li>Localization support</li><li>RSpec test helpers to ensure your Webpack bundles are ready for tests</li></ol><p>Additionally, we have a vibrant community of production projects using React on Rails.</p><p>Here’s a quick video walkthrough of creating a new Rails app with Webpacker and adding React on Rails.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FM0WUM_XPaII%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DM0WUM_XPaII&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FM0WUM_XPaII%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/70e1b4ab745ea7608b916d96c546bb5c/href">https://medium.com/media/70e1b4ab745ea7608b916d96c546bb5c/href</a></iframe><p>With the Webpacker integration and the default Webpack setup, there’s not much complexity with adding React on Rails to a Rails app for server rendering with React + Redux + React Router.</p><p>My next article will document migration details of moving from v7 or earlier to v9.</p><p><a href="mailto:justin@shakacode.com">Please reach out to me</a> if my team at ShakaCode can you help you with your React or React-Native apps, with or without Rails on the backend. The use of React on Rails should be ideal for legacy jQuery or Angular apps that wish to convert to using React with Rails.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f2584c6c8fa4" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/introducing-react-on-rails-v9-with-webpacker-support-f2584c6c8fa4">Introducing React on Rails v9 with Webpacker Support</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Front-End Sadness to Happiness: The React on Rails Story at GORUCO 2017]]></title>
            <link>https://blog.shakacode.com/front-end-sadness-to-happiness-the-react-on-rails-story-at-goruco-2017-d63b8fd26ca4?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/d63b8fd26ca4</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Justin Gordon]]></dc:creator>
            <pubDate>Sat, 15 Jul 2017 01:27:01 GMT</pubDate>
            <atom:updated>2017-07-15T08:38:51.225Z</atom:updated>
            <content:encoded><![CDATA[<p>Here is a short recap of my odyssey around 4 major US cities giving talks on React on Rails in June of 2017. This talk focused on the “Why?” of <a href="https://github.com/shakacode/react_on_rails">React on Rails</a>. Please don’t hesitate to email directly at <a href="mailto:justin@shakacode.com">justin@shakacode.com</a> if you think that my team and I can help you with React on Rails, React-Native, or converting your Rails+Angular app to Rails+React. We’re helping several great companies with these awesome technologies.</p><h3><strong>Saturday, June 24th, </strong><a href="http://goruco.com/#speakers">GORUCO in NYC</a></h3><h4>Front-End Sadness to Happiness: The React on Rails Story</h4><p><strong>Abstract: </strong>Standard Rails development made me happy like no other programming paradigm in my career. Simple front-end development with standard Rails and a sprinkling of jQuery was ‘OK’ Then, in 2014, I had to build a front-end that dynamically updated like a desktop app. I knew there had to be something better, and I went down the rabbit hole of integrating React with Rails using Webpack. Come find out how my obsessive pursuit of “developer happiness” for the Rails front-end eventually drove me to start the React on Rails gem, the most popular integration of Rails with React using Webpack.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FSGkTvKRPYrk%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DSGkTvKRPYrk&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSGkTvKRPYrk%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ad865efbfffdbfb5faac505577567e07/href">https://medium.com/media/ad865efbfffdbfb5faac505577567e07/href</a></iframe><p><a href="https://goo.gl/2QR4sw">GORUCO 2017: Front-End Sadness to Happiness: The React on Rails Story</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/690/1*WyaLz9l4B2kJX2op8fGrcw.png" /><figcaption>The Basis of Rails and React on Rails</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0Ah2vLPtVpB5JC47C-es2g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UrsKj-mOhyK3uxiAbB1JvA.png" /><figcaption>GORUCO 2017 Speakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4sPi0GGWwrtujSl1Xt1i3w.png" /><figcaption>GORUCO 2017 Speakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6462Cuko6TXb1l4Fs_0l2Q.jpeg" /><figcaption>Justin and GORUCO Conference Organizer Luke Melia</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P0M61KwCQYX82R5opPifWw.png" /><figcaption>Justin with the PolicyGenius team</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q6z-lb7gW_fy6LU3oVWStQ.png" /><figcaption>Conference organizers Jesse Chan-Norris and <a href="https://medium.com/u/12b4a08e3a2e">Mike Dalessio</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xyZKnOzJRF-jKmBtPMh08Q.png" /><figcaption>Great views from the GORUCO conference location</figcaption></figure><p>Click for <a href="https://goo.gl/W2FzKa">more photos from GORUCO 2017</a></p><h3><strong>Thursday, June 8th</strong>: LA Ruby</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YglsDC7Mft0DiUkQBA1hiQ.png" /><figcaption>The LA Ruby Meetup crew, June 8th, 2017</figcaption></figure><p>Click for <a href="https://goo.gl/KnZpnM">more photos</a> from the LA Ruby meetup.</p><h3><strong>Tuesday, June 13th</strong>: Pivotal Labs, Santa Monica, CA.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_nCu3llyLLACtC6jxxdo4Q.png" /><figcaption>Justin at Pivotal Labs, Santa Monica, June 13, 2017</figcaption></figure><h3><strong>Tuesday, June 20th</strong>: Pivotal Labs, San Francisco, CA.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iRRPLnEqp8j5CuVvvDy94A.png" /><figcaption>Justin at Pivotal Labs, San Francisco, June 20, 2017</figcaption></figure><h3><strong>Thursday, June 22nd, 7 pm</strong>: NYC.rb Meetup</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BF-pv8_JE0acI6dEiJwpUw.png" /><figcaption>Event coordinator Rashaun, aka “Snuggs”</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z4_GlDOXw8KF8v0nYQW0Qw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MBBJj3xCc3VVpPSleTwnMQ.png" /><figcaption>No joke. Snuggs introduced me while doing a handstand.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-x744QuC2LuOoxqBy74-wA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_UCy2GgGae3O7lhgUbxowg.png" /><figcaption>The clerks had matching shirts! Late night water run.</figcaption></figure><p><a href="https://goo.gl/i4w5Ev">Click for more photos from the NYC.rb meetup</a></p><h3><strong>Tuesday, June 27th</strong> at 6:30 pm: Austin on Rails</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*51VPP5nejfFjta8IGdlURg.png" /><figcaption>Justin with Richard Schneems at Austin on Rails, June 27th, 2017</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K-sraIDX23DrWOnF7YoaRQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6Lena6xFhtWxh5pTk989_A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R8Y4iDK1wnltCgtmoXNNDw.png" /><figcaption>Had to get some tacos in Austin!</figcaption></figure><p><a href="https://goo.gl/J6a8Ms">Click for more photos from my Austin visit</a></p><p>I’m happy to provide a free, 30 minute video chat consultation to discuss your web or mobile application development needs. Please get in touch at <a href="mailto:justin@shakacode.com">justin@shakacode.com</a>. You can follow me <a href="https://twitter.com/railsonmaui">@railsonmaui</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fc99775%3Fas_embed%3Dtrue&amp;url=https%3A%2F%2Fupscri.be%2Fc99775%2F&amp;image=https%3A%2F%2Fupscri.be%2Fmedia%2Fform.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/f0e62491f524a255884db2203a86c64e/href">https://medium.com/media/f0e62491f524a255884db2203a86c64e/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d63b8fd26ca4" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/front-end-sadness-to-happiness-the-react-on-rails-story-at-goruco-2017-d63b8fd26ca4">Front-End Sadness to Happiness: The React on Rails Story at GORUCO 2017</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimized, Parallelized CircleCI Configuration for ReactOnRails]]></title>
            <link>https://blog.shakacode.com/optimized-parallelized-circleci-configuration-for-reactonrails-3489e59ac012?source=rss----dbc83ae6fe51---4</link>
            <guid isPermaLink="false">https://medium.com/p/3489e59ac012</guid>
            <category><![CDATA[react-on-rails]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[codecov]]></category>
            <category><![CDATA[circleci]]></category>
            <category><![CDATA[jest]]></category>
            <dc:creator><![CDATA[Rob Wise]]></dc:creator>
            <pubDate>Wed, 21 Jun 2017 04:22:44 GMT</pubDate>
            <atom:updated>2017-06-21T04:03:56.255Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RCEk8gamSYXjIlngRefvnw.png" /></figure><h4>ReactOnRails + Jest + CodeCov + CircleCi Parallelization</h4><p>At <a href="http://www.shakacode.com/">ShakaCode</a>, our internal app, <a href="https://friendsandguests.com/">FriendsAndGuests</a>, tends to be our guinea pig for the bleeding-edge use cases of <a href="https://github.com/shakacode/react_on_rails">ReactOnRails</a>. Just getting CI to work was no exception. There are a lot of workarounds and “gotchas,” but this should hopefully save you the pain I went through. We chose to use <a href="https://circleci.com/">CircleCI</a> as our CI provider and <a href="https://codecov.io/gh">CodeCov</a> as our code coverage provider. This guide assumes you’ve read through the basic documentation for both.</p><h3>Parallelization</h3><p>When your app starts to scale, your test suite is inevitably going to get slower. Your first line of defense should always be to stay judicious with what and how you test (see Martin Fowler’s <a href="https://martinfowler.com/bliki/TestPyramid.html">Test Pyramid</a>). Still, this slowdown is inevitable with growth. CircleCI has a great feature called <em>parallelization</em> that allows you to easily configure your tests to run across multiple containers. Parallelizing your build can greatly increase your speed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OVR8kopDYzlOFVKQFnWQeg.png" /><figcaption>CircleCI let’s you easily add more containers. With the proper setup, it’s like a “instantly make my test suite faster” button!</figcaption></figure><p>If your testing frameworks can be configured to use JUnit reporters (as <a href="https://circleci.com/docs/test-metadata/#rspec">RSpec</a>, <a href="https://github.com/michaelleeallen/jest-junit-reporter">Jest</a>, and <a href="https://circleci.com/docs/1.0/test-metadata/#a-nameeslintaeslint">ESlint</a> can), CircleCI will read those reports, figure out the median time to test each file, and then properly distribute those tests across the containers. Distributing the files in this way ensures that one container doesn’t end up with only fast unit tests and the other with only slow feature specs. You want the containers to finish their suites around the same time—you’re only as fast as your slowest container.</p><p>As a bonus, if any tests fail, they show up in an easy-to-read format right at the top of the page. That means no more searching through endless lines of noise to find your failing test.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mvX29AsMnlJvJVNllaFAww.png" /><figcaption>Using a JUnit reporter makes for pretty test summaries that show right at the top. No more sifting through hundreds of lines of noise to find your failing test!</figcaption></figure><p>If your tool does not have a JUnit reporter but still allows for passing files via the command line in a space-separated format (by the way, scss-lint, slim-lint, and rubocop all let you do this), then you can still use parallelization! The only difference here is that CircleCI won’t be able to tell how long each file takes to be run through the tool, so it falls back to using file size and you may not get as well-calibrated division of the files across the containers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*igSHvCHA9Ps4-KpZwrZhnQ.png" /><figcaption>CircleCI reverts to using file size to split up your tests across containers if it can’t find the corresponding Junit information</figcaption></figure><p>Here’s a list of tools we currently use where we can’t use parallelization:</p><ul><li>brakeman</li><li>flow</li><li>bundle-audit</li></ul><h3>CodeCov Flags</h3><p>One of the cool new features coming out of CodeCov is the use of <a href="https://docs.codecov.io/v4.3.0/docs/flags">flags</a>. They allow you to easily split up the coverage of different test suites.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GKSU8ldGbHwO9YXwa-A4TA.png" /><figcaption>CodeCov “flags” in action for a backend-only PR</figcaption></figure><p>I’ve got guys on my team who only do backend and likewise guys who only do frontend, and they don’t care about each others’ code coverage, so why combine the two? Flags allow you to do that.</p><h3>circle.yml</h3><p>There’s a lot going on here, make sure you’re up to speed with the basics of how CircleCI works and what different options mean. Also, watch out for those pwd: client lines, that means we’re running all of the commands in the “present working directory” of the client folder.</p><pre>machine:<br>  environment:<br>    RAILS_ENV: test<br>    RACK_ENV: test<br>    YARN_VERSION: 0.24.6<br>    PATH: &quot;${PATH}:${HOME}/.yarn/bin&quot;<br>  node:<br>    version: 7.7.3</pre><pre>dependencies:<br>  pre:<br>    # Install Yarn<br>    - |<br>      if [[ ! -e ~/.yarn/bin/yarn || $(yarn --version) != &quot;${YARN_VERSION}&quot; ]]; then<br>        echo &quot;Download and install Yarn.&quot;<br>        curl -o- -L <a href="https://yarnpkg.com/install.sh">https://yarnpkg.com/install.sh</a> | bash -s -- --version $YARN_VERSION<br>      else<br>        echo &quot;The correct version of Yarn is already installed.&quot;<br>      fi<br>  cache_directories:<br>    - &quot;~/.yarn&quot;<br>    - &quot;~/.cache/yarn&quot;<br>  override:<br>    - yarn install --no-progress --no-emoji<br>    - bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3<br>  post:  <br>    - yarn run build:all:rspec:<br>        pwd: client<br>    - mkdir -p $CIRCLE_TEST_REPORTS/jest<br>    # HACK: junit-reporter fails if file doesn&#39;t already exist<br>    - touch $CIRCLE_TEST_REPORTS/jest/test-results.xml</pre><pre>test:<br>  override:<br>    - bundle exec rspec -r rspec_junit_formatter --format progress --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml:<br>        parallel: true<br>        environment:<br>          CODECOV_FLAG: backend # tags all Ruby tests<br>        files:<br>          - spec/**/*_spec.rb<br>  post:<br>    # HACK: for why maxWorkers is needed, see <a href="https://github.com/facebook/jest/issues/535#issuecomment-171445481">https://github.com/facebook/jest/issues/535#issuecomment-171445481</a><br>    - $(yarn bin)/jest --testResultsProcessor jest-junit-reporter --coverage --maxWorkers 3:<br>        pwd: client<br>        environment:<br>          NODE_ENV: test<br>          TEST_REPORT_PATH: $CIRCLE_TEST_REPORTS/jest # used by jest-junit-reporter<br>        files:<br>          - &#39;app/**/*.spec.js&#39;<br>          - &#39;app/**/*.spec.jsx&#39;<br>    - $(yarn bin)/codecov -p .. --F frontend:<br>        pwd: client<br>        parallel: true<br>    # Other stuff such as rubocop, eslint, flow, scss-lint, brakeman, bundle-audit</pre><pre>general:<br>  artifacts:<br>    - tmp/capybara # great for debugging feature test screenshots<br>    - log/test.log # sometimes needed for hard-to-track bugs<br>    - tmp/brakeman-report.html # if you&#39;re using brakeman</pre><h4>yarn</h4><p>Since we’re using yarn instead of npm, we need to use override during the dependencies step to avoid installing via npm. That means we now need to manually run bundle check and bundle install as well.</p><p>We deviate a bit from the <a href="https://circleci.com/docs/1.0/yarn/">docs regarding yarn</a> because sometimes we want to install newer versions of yarn than what comes with the CircleCI container. We use a simple shell script and cache technique that CircleCI itself used to recommend before they added built-in yarn support. In the post step, we build our webpack bundles ahead of time.</p><h4>RSpec</h4><p>Although CircleCI can automatically detect we are using Ruby and configure itself correctly, we have to override this and run RSpec ourselves because we want to specify the custom environment variable CODECOV_FLAG so that CodeCov will know that these are backend tests.</p><h4>Jest</h4><p>Next, we run Jest. We’re not using our normal test script from the package.json because we need to do some special things for CI. Jest has a <a href="https://github.com/facebook/jest/issues/535#issuecomment-171445481">weird issue</a> on CircleCI where it can go over memory if you don’t limit the number of workers. To get around this, we can specify that the maxWorkers is 3. While we certainly <em>could</em> run Jest in parallel, there seems to be some type of strange issue with how the code coverage results get merged together across containers, so opt not to do it here.</p><h4>Jest JUnit Reporter</h4><p>In order to get JUnit output (again, this allows for those nice little errors at the top of the page), we need to specify using jest-junit-reporter via the --testResultsProcesser flag. The test results file must be put in a place where CircleCI can find it, however, so we need to use the special TEST_REPORT_PATH that the jest-junit-reporter package will pick up (<a href="https://github.com/michaelleeallen/jest-junit-reporter#usage">docs</a>). Unfortunately, there seems to be a bug where if the file does not already exist, the process fails, so we need to put create a blank file at that location first using the touch command.</p><h4>Jest Coverage</h4><p>Then, we tell Jest to collect coverage with the --coverage flag. After the tests run, we can use the codecov package to upload the results. We must take care to tell it that the root of the project is actually a folder level up using -p .., otherwise CodeCov will get confused and think that your Rails app folder is the same folder as the client/app folder! While we’re at it, we pass the -F frontend flag to tag our coverage as frontend.</p><p><em>Note: Don’t use </em><em>--root or </em><em>--flags as the CLI help recommends; these don’t actually work. Use the short versions I listed above. Also, see comment in the “Jest” section about parallelization needing to be turned off due to coverage report merge problems.</em></p><h3>codecov.yml</h3><pre>coverage:<br>  status:<br>    project: off<br>    patch:<br>      frontend:<br>        flags: frontend<br>      backend:<br>        flags: backend</pre><pre>flags:<br>  backend:<br>    paths:<br>      - app<br>      - lib<br>      - db<br>  frontend:<br>    paths:<br>      - client</pre><p>Here’s how we set CodeCov to give us separate frontend and backend coverage status (I prefer to only see the patch status so I turned project off). Note that the <a href="https://docs.codecov.io/docs/node#section-partial-line-coverage">partial line coverage feature</a> seems to cause “file not found in report” errors in CodeCov when trying to view your files, so I don’t enable it here.</p><h3>client/package.json</h3><pre>// ...<br>&quot;devDependencies&quot;: {<br>  // ...<br>  &quot;codecov&quot;: xxx,<br>  &quot;identity-obj-proxy&quot;: xxx,<br>  &quot;jest&quot;: xxx,<br>  &quot;jest-junit-reporter&quot;: xxx,<br>},<br>&quot;jest&quot;: {<br>    &quot;collectCoverageFrom&quot;: [<br>      &quot;app/**/*.{js,jsx}&quot;,<br>      &quot;!**/types/**&quot;<br>    ],<br>    &quot;coverageReporters&quot;: [<br>      &quot;lcov&quot;<br>    ],<br>    &quot;moduleNameMapper&quot;: {<br>      &quot;\\.(css|scss)$&quot;: &quot;identity-obj-proxy&quot;<br>    },<br>    &quot;resetModules&quot;: true,<br>    &quot;resetMocks&quot;: true,<br>    &quot;roots&quot;: [<br>      &quot;&lt;rootDir&gt;/app/&quot;<br>    ]<br>  }<br>}</pre><p>Most of this is self-explanatory if you’ve read the documentation. We are using the identity-obj-proxy package to fake our css and Sass files during Jest testing since Webpack usually handles that. You may need to <a href="https://facebook.github.io/jest/docs/webpack.html#handling-static-assets">make a file mock</a> for other types of imports. Babel support is automatically included in Jest’s core, so no need to configure anything there.</p><p><em>Note</em>: <em>You may also need to set up any aliases you’ve made with Webpack, but my colleague Alex Fedoseev set us up with </em><a href="https://github.com/tleunen/babel-plugin-module-resolver"><em>babel-plugin-module-resolver</em></a><em> and has eliminated our need to do that!</em></p><p>Additionally, the Jest coverage output can get kind of spammy because it spits the entire coverage file to STDOUT, so we override that with coverageReporters so that it uses lcov only (this is the type that’s needed by CodeCov). No more spammy output!</p><h3>spec/rails_helper.rb</h3><pre>if ENV[&quot;CI&quot;]<br>  require &quot;simplecov&quot;<br>  require &quot;codecov&quot;</pre><pre>SimpleCov.formatter = SimpleCov::Formatter::Codecov<br>  SimpleCov.start(&quot;rails&quot;)<br>end</pre><pre>unless ENV[&quot;CI&quot;]<br>  ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)<br>end</pre><p>Here we startup SimpleCov with CodeCov as the formatter. In addition, we use ReactOnRails’s test helper in development to make sure we don’t forget to run our tests against stale Webpack bundles. However, we already made sure to build the bundles in our circle.yml config, so we can skip this step when in CI.</p><h3>Gemfile</h3><pre># ...</pre><pre>group :test do<br>  gem &quot;codecov&quot;, require: false<br>  gem &quot;rspec_junit_formatter&quot;<br>end</pre><p>Self-explanatory, and that’s it!</p><h3>bonus: flow</h3><p>If you use <a href="https://flow.org/">Flow</a>, it can take a while to initialize the server. You can tell CircleCI to start up the server in the background at the beginning of your test suite. Assuming you’ve got enough jobs going on (so that you avoid a race condition)your server finishes starting up, then when you start your Flow check, it should be pretty much instantaneous.</p><pre>test:<br>  pre:<br>    - $(yarn bin)/flow start: # start up flow server in background so it&#39;s ready to go<br>        pwd: client<br>        background: true</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3489e59ac012" width="1" height="1" alt=""><hr><p><a href="https://blog.shakacode.com/optimized-parallelized-circleci-configuration-for-reactonrails-3489e59ac012">Optimized, Parallelized CircleCI Configuration for ReactOnRails</a> was originally published in <a href="https://blog.shakacode.com">ShakaCode</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>