1,200 commits later and the MarketInvoice rebrand is live. You can see our rebranded website on marketinvoice.com. I was going to give a technical talk at @Adams conference about our journey from MVP to production but since the conference has been rescheduled to next year, I’ll write about our experience instead.
- Performance: server side initial render. 55% faster load time, 28% smaller page size
(score, load time, page size)
(score, load time, page size)
|Pingdom||63 / 100, 2.81s, 1.8mb||81 / 100, 1.3s, 1.3mb|
|Google PageSpeed: mobile||55 / 100||65 / 100|
|Google PageSpeed: desktop||73 / 100||84 / 100|
- Performance: client side subsequent render. Up to 6x faster load time, 90% average smaller page size. Since the rebranded site is an SPA, when the user navigates to a different page (and triggers a client side render) only those resources unique to the requested page are requested leading to the large performance boost.
- 3x faster dev builds via hot reloading
- Confidence in our codebase; thoroughly unit tested front end React components, Redux state management, and Node.js back end middleware (400+ tests, 80%+ coverage)
- Under 20 minutes to get code through CI processes and out to production. We now release from Github too so no need to manually deploy from AWS as we did previously, this ties up release notes and commit history nicely
- MarketInvoice has grown into a Business Finance company and this identity shines through with the rebrand. Even when raising issues, customers say they like it.
- Recruiting and retaining good developers to work on our public website’s codebase should be less difficult as we’re aligned to good practices from the start (TDD, CI, DRY)
MarketInvoice had been developing the capabilities to expand beyond Invoice Finance and step into the £35bn market of business loans. Led by @Bri, a rebrand was on the cards.
It was an opportunity to rethink the existing public website architecture which was based on Node.js on the backend and a vanilla frontend (html, css, js) with embedded Angular apps. Rebranding is the culmination of many things; logo, colour, tone, and perception to shape an identity. Our existing architecture meant that if we wanted to change something on the navbar, for example, about 120 html files would need changing. That’s not a fun code review.
Developers including @matt had been looking at next.js, a framework for server side rendered React applications. It promised the fast load time and SEO support of a server rendered site and the benefit of a Single Page Application (SPA).
Having benchmarked and evaluated the strengths and weaknesses of our current site after joining the team in April, I put together a prototype next.js site to get a feel for the level of complexity involved. We’d need a backend api to handle redirects and serve data such as the live amount funded figure. Redux was also integrated to manage client side state to minimize the number of api requests clients have to make. Finally the front end would need to feature core React components (connected, stateful, stateless) which included the navbar, footer, hero, from which a small clone of the website could be created and compared. For styling we chose SCSS because at the time js styles would cause jank on initial render.
In a public talk, I showed that the architecture’s performance scores were in their high 90s. In hindsight this was too good to be true as it didn’t include third party dependencies from Google Tag Manager. However even after these dependencies were loaded into our site there’d be a chasm between our old site and the prototype.
After seeing the prototype up close, the two thorniest questions that came out of a front end working group put together by @Jason were; how are third party integrations such as segment analytics handled in SPA mode, and is there an incremental path to developing the rebranded site.
Since the 3rd party integrations ultimately made calls to external api, they were put through the Redux thunk flows, just like other actions with side effects or async behaviour.
We considered tools like Toga but there was no easy path to incremental development; unfortunately it’d have to be ‘big bang’. One reason was technical; next.js takes both the front and back end under its wing, the other was brand; we’d change copy throughout the site so until launch two branches would have had to be maintained.
@piers took the design lead while I focussed on development. A step change in the quality of our codebase occurred after pair programming with my mentor @Leon. He demonstrated the both the philosophy and process of TDD. All new components were developed TDD and prior components had regression tests added as we went.
This worked well but a few months later the repetitiveness of setting up the scaffolding for tests was weighing down. Through a couple of Innovation Days (one day a fortnight engineers can work on an idea outside their set of user stories) using @Mason’s CLI boilerplate generator library as inspiration, I built a CLI React template generator to scaffold both the new component (stateless functional, stateful class, connected class) and its associated test.
Through pair programming and mentoring, Piers began the transitioned from designer to developer in a React ecosystem doing TDD both of which he’d not experienced before. Being able to script out the starting point for a new component and test helped get him started. The other thing which helped was the use of PropTypes throughout; both for thinking of UI as a function and the being clear on the types of props the function expected.
On the back end, api and redirect logic were refactored into middlewares. Before joining MarketInvoice I interviewed with @Dominic. I was caught lacking on fundamentals. One in particular was currying. We’re using currying for dependency injection which keep our middleware testable, I appreciate the questions he asked now.
Browserstack proved to be useful for testing across browsers and devices. Since it’s screenshot feature tests across dozens of devices but occasionally produces false positives, our process was to screenshot dozens of devices and live test those devices not rendering properly. CSS Flexbox is awesome but IEs inconsistent application of the current spec meant we had to vendor prefix some styles. Damn IE.
We accrued some technical debt along the way by bringing forward the css build file from our old site. This helped propel the prototype but has led to class clashes the necessary use of !important in our scss. We also rely on a script which in turn depends on jQuery. Just removing these will have a measurable impact on performance. We’ve started by refactoring the functionality into a component.
Styling is the weakest part of our application as it’s not testable since it’s divorced from UI e.g. changing a component’s scss won’t break it’s jest snapshot test. It’s a big change but using js styles within components may be a better fit long term.
Upgrading next.js to run React fibre and streams promises to be up to 2.4x faster, so that’s likely in the pipeline.
The past several months have been intense. Pursuing the Udacity nanodegree (sponsored by MarketInvoice through their training budget) helped bed in fundamentals from declarative vs imperative programming to variable scope in ES6 which were felt in this codebase. When I set out working on this project I wanted to help create something I could be proud of in years to come. I think we’ve done that.