Bridging the old and new of web development


What do you do when you have a large system that has been built up over many years, services a huge amount of your customers, and you want to improve conversion?

Over the last 18 months, we have worked to rebuild the user interface of trainline so that it appears more modern, whilst still working on top of the codebase that has worked for many years. We transformed our core booking flow UI to go from something that came out of the early 2000s, into a modern responsive website. This all with the help of great frameworks out there like Bootstrap and Knockout, along with Jasmine and CasperJS for our testing.

So for our customers, this fresh coat of paint helps our website work well from mobile, tablet, and desktop, and it has had a greatly positive impact on our customers.

However, our shiny new user experience quickly showed how our technical implementations were far from the ideal.

  • We were still on our original codebase for our server side handling
  • Our JavaScript dependencies were growing excessively large
  • Our testing was producing a lot of interference with each other
  • Knockout’s two way binding wasn’t entirely efficient
  • Our code was dumped into one big bucket
  • And no server side rendering

In our quest in trying to break away from a monolithic approach, we ultimately built another.

So we started to look outwards and see what others were doing. The new kid on the block is React. There are many tutorials out there about it so I won’t go into how to use it, but the primary benefits to us were:

  • Ability to start thinking about componentization
  • Unit testing exact components
  • Creating compositions of many components to be another component or a page
  • Server side rendering
  • And greater code reuse for both server side and client side

Internally, we have now set up TeamCity to build many small components and publish them to an internal npm repository. This is then consumed by other React components, and built outwards to compose our pages.

Now with much of our code living in JavaScript this offers us the ability to start to look at using node.js. However, what do you do with your current solution?

With pages that are currently on our existing code base (which we are not yet able to rebuild entirely), reuse is key for server side logic whilst also making use of the newly created React components. Reactjs.net allows us to do as such, whilst providing us with the server side rendering feature through the use of managed V8 engines. However, we found issues including large memory footprint and sporadic failures occurring.

Another great library is edge.js which allows for interoperability between .NET and node.js. With node.js being more production tested and able to handle the large amount of traffic, it took one developer a couple of days to put together a wrapper to achieve the same result that Reactjs.net performed.

But what about new pages? We want to build them in a way to work purely in node.js, but also to work with our present .NET solution. Whilst .NET has many who love it, myself included, we want to reuse code as much as possible, and node.js has proven to be the case. Running JavaScript on both server side and client side allows implementation and testing of business logic in one language (rather than two – .NET for server side and JavaScript for client side), and with React components combined with flux architecture, this is now a lot more achievable then it was 18 months ago.

So how do you move from a solution written in .NET to node.js without a big bang approach?

old-to-new-webflow

With pages that we are looking to use node.js for, node.js will handle the initial request, executing validation and surface level business logic. On the same web server would be an internalised WebAPI which acts as a middleman to the existing .NET solution. This would look to take care of session state, authentication, and other remaining services, up until a point where it can be replaced by a node.js approach. We can also look to call code in the existing .NET solution for further reuse, however this will be kept to a minimum so we’re not coupled to it.

Having this clean layer of separation allows us to see the clear divide between the old and the new, whilst allowing business to carry on as usual. Furthermore, this divide establishes the parts to replace as our architecture within the company changes.