By Jamie English — May 2015 — 2 min read

Our website source code is no longer open source on GitHub. We are planning to release a more generic boilerplate project.

We recently deployed and open sourced a new version of our website. We've had some great feedback on how fast the site is so we wanted to give a high level overview of our technical approach in the hope that others will find it useful.

In this post we'll cover both how we made the site so fast and what our development setup looks like.

Performance

When browsing gocardless.com you'll notice that after the initial page load navigation around the site is super snappy. Until you leave our splash pages, or choose a different locale, all your browser is requesting are new images. If you happen to be on a slow connection, or you have disabled JavaScript, the site still works fine.

React

Using React to render on the server means that we can deliver not only a fully rendered page to the browser, but also the rest of our website too. Once the initial page is displayed, a request is made to fetch the rest of the site as a React application (only 250kB). All subsequent navigation within the website is blindingly fast, not suffering the latency of HTTP requests since the browser already has the whole app.

If the user has disabled JavaScript, or they are on a poor connection and the JavaScript takes a while to load, they still experience the fully rendered page and only miss out on the fast navigation.

Static deploy

While we develop against an Express server, we don't deploy that. Since gocardless.com is entirely static, we're able to deploy and serve static HTML. One huge benefit of this is that we can host the site off an S3 bucket and not have to worry about a running web server and everything that goes along with it, such as exception handling, monitoring, security issues, etc.

In order to generate our static HTML we need to know every available URL. Since we're keeping all of our routing configuration in one place, this is trivial; we're able to easily extract the paths for all pages in every locale. Once we have those URLs, we simply crawl our locally running Express app and write the responses to disk ready for deployment.

Babel

The newest version of JavaScript, ES6 (or ES2015 as it's now known), contains numerous improvements that make building applications in JavaScript a much nicer experience. We use Babel which makes it possible to take advantage of language additions now by compiling ES2015 (and even ES7 code) down to ES5, which has much better browser support.

webpack

We use webpack to bundle our CSS and JavaScript. There are plenty of other tools which do that too, however we particularly love the development experience when using the React Hot Loader plugin for webpack. This lets us see our changes live in the browser without losing app state.

Immutable

The main motivation for rebuilding our website was to allow us to more easily manage pages across different locales. We wanted to be able have one place where we could see, for each page, its handler, which locales it was available in, and its route for that locale.

Having one data structure holding all of this information means that you can see the structure of the entire site in one place. A downside of this is that it can get a bit tricky querying such a large and nested structure. Since the whole application relies on this structure, we also need to be really careful not to accidentally mutate it. This is typically dealt with by lots of defensive cloneDeep ing. Not doing so would (and initially did) lead to subtle, hard to diagnose bugs across the application.

Our solution to the above problems was to use Facebook's Immutablelibrary. Using immutable data structures, such as Map and List , means that we don't have to worry about mutating the actual routes data structure as it gets passed into functions that operate on it. Immutable also has a great API for dealing with nested properties, including getIn and setIn , which we use extensively.

Conclusion

We're pretty happy with the simplicity of our solution and the user experience that it enables. We hope others can benefit from our experience and, of course, if you have any feedback or suggestions, please get in touch!