Your friends at Viget present Extend, a Code & Technology Blog


Deep Dive: Building Know Lupus with React.js

This May, Viget worked with the Lupus Foundation of America to launch Know Lupus (case study) (site), a React.js-based game that teaches you about Lupus with bouncy cards and colorful illustrations. It was my first chance to work with React on a real project, so I had a blast but also learned some lessons that’ll save me time on the next project (and maybe, you too!).


Why React?

I worked with Backbone and Marionette on several other projects including DSG Running (case study) (site), and got tired of the amount of boilerplate needed to create simple elements and render them inside each other. Furthermore, Backbone’s loose model-view relationship doesn’t fit so well with highly motion-based sites — managing animation, sounds, and interface states through models can get complex quickly.

In React, making a component is as simple as typing HTML inside render(). If you want to break it up, just import smaller components and include them as <Components /> in the JSX. This is much, much smoother than managing views in Backbone, where even with the assistance of Marionette you end up defining regions by writing code in a template and transforming it to a region with an addRegions selector.

But state management is where the React + Flux architecture really shines. The state of your app is stored in a central location — at the top of the structure — and the changes trickle down through the components. You fire off Actions from anywhere in the app, and the Store listens and changes state appropriately, then broadcasts the updated state to your tree of React components. This separation seems complex at first, but in the end you write much simpler code in a place where you can easily find it, vs splitting it across several models and re-renders like you would in Backbone.

Webpack

Another important piece of Know Lupus was Webpack, another technology I was working with for the first time. Webpack is a next-level build tool like Gulp (which we've talked about before), but with a focus on connecting assets to each other via dependencies. Essentially, Webpack understands a lot more about your code than other build tools do, so it can do advanced optimizations and update code on the fly. With Webpack, I used React Hot Loader to update components and styles in real-time, trim unused code from my package automatically, and embed SVGs in my JS bundle for faster all-in-one loading.



During deploy, React-To-HTML rendered the app as static markup, and inlined my CSS into the same file. The result is a single HTML file so the intro screen actually renders on the first request. All these tricks resulted in a pretty great webpagetest.org result for a JS app.

Webpack is my build tool of choice going forward. If you haven’t, you should check out Pete Hunt’s tutorial on how to get started with it.


CORS: You’re Doing It Wrong

If you’re serving font files from a CDN (content delivery network) and using an overly permissive CORS policy, you’re doing it wrong. I’ll show you how to serve those files with an appropriately restricted policy.

When you’re serving assets from a different domain (using a CDN), something like https://asdf98as9asd.cloudfront.net/assets, you’ll often see an error like:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://asdf98as9asd.cloudfront.net/assets/my-licensed-font.woff. This can be fixed by moving the resource to the same domain or enabling CORS..

When you Google that error message, almost every result suggests that you add a web server configuration to allow serving your assets with a custom Header value of Access-Control-Allow-Origin = "*".

However, if you’re using licensed font files this is not what you should use! This setting would allow any other site to use your font assets by using the URL to your font file in their CSS.


Bandwidth-Aid: A VPN disconnect reminder script

VPNs are great for allowing you to do certain things that require being on your company's network while you're on an external internet connection. At Viget, we use a VPN for a number of activities: connecting to internal servers, viewing secure internal websites, deploying the latest code to certain servers, etc.

Recently, while working from home, I kept noticing that my internet felt slow. I'd hop on over to speedtest.net and see much lower than expected results. Before calling up my ISP, I noticed that I had forgotten to disconnect from the VPN! Connected for 8-15 hours, routing all of my traffic through our company's private network! :(

So, I came up with a solution: a small ruby script that runs every 10 minutes to check whether I'm connected to the VPN, and if I have been for more than 10 minutes, yell at me.


SimplestStatus — An Enhanced Enum Implementation for Any Version of Rails

While working on a recent project, I ended up with three different models with integer-type status columns and nearly identical status-related functionality. They looked something like this:

class Post < ActiveRecord::Base
  DRAFT     = 0
  PREVIEW   = 1
  PUBLISHED = 2
  ARCHIVED  = 3

  STATUSES = {
    DRAFT     => :draft,
    PREVIEW   => :preview,
    PUBLISHED => :published,
    ARCHIVED  => :archived
  }

  STATUSES.each do |value, name|
    scope name, -> { where(status: value) }

    define_method "#{name}?" do
      status == value
    end

    define_method name do
      update_attributes(status: value)
    end
  end

  validates :status, presence: true, inclusion: { in: STATUSES.keys }
end

Having an integer-type status column gave me more flexibility over the number of statuses — as well as the flexibility to change the name of a status without having to make any database migrations (which would have been the case if I was storing strings). In my case, this was worth the tradeoff of the database having a different understanding of the data than the application.

After the third model, it was time to DRY things up. First, I thought about the simplest DSL to get me all the status functionality I needed, which led to the following:

class Post < ActiveRecord::Base
  statuses :draft,
           :preview,
           :published,
           :archived
end

As a result, SimplestStatus was born!