Removing Dependencies

Over the last few weeks, we've been cleaning up the dependencies in our Swift Talk backend. Now that we're done, we finally feel like we're on top of the code base again. No more dark, dusty corners!

In this post, we'll outline how the code base has developed over time, and the changes we've made to clean it up.

We started developing the Swift Talk backend almost three and a half years ago. To begin with, we hired a contractor to build the site using Ruby on Rails. After we launched, we continued to make small changes ourselves, and hire other contractors for larger things.

When we decided to rewrite the backend in Swift last fall, our goal was to get the new backend up and running as quickly as possible. For the most part, we replicated what the Rails backend was doing before. To focus on building the most interesting parts of the site, we included third party libraries for dealing with PostgreSQL, XML, and crypto functions. We also kept all the CSS and Javascript infrastructure around, serving the same .css and .js files as before, just from our Swift server.

A few things bothered us about the state of this code base:

  1. Some of the Swift dependencies felt unnecessary, given the little code it would take us to directly interface with the underlying libraries.

  2. We didn't understand the Javascript build stack (lots of node modules, browserify, and babel), and the deprecation warnings in the JS build process were starting to accumulate.

  3. We ended up shipping huge CSS (2 MB uncompressed) and Javascript (7.3 MB uncompressed) files, although they were doing very little to enhance the functionality of the site. For example, the subscription form was built using React, which adds a massive amount of code for a small subsection of the site.

With regard to the Swift dependencies, we ended up writing our own lightweight wrapper around libpq, similar to the wrapper we demonstrated on Swift Talk. Our wrapper is approximately 300 lines of code, almost half of which are straightforward mechanical conversions between Swift types and their representations in PostgreSQL. We're happy to maintain this small piece of code against a mature library like libpq ourselves. The benefit is that we can easily fix warnings that arise with new Swift versions, fix bugs as we encounter them, or make changes to the API so that it better suits our needs.

We also removed our dependency on BlueCryptor, a Swift wrapper around CommonCrypto on macOS and libcrypto on Linux. Since we were only using it to create md5 hashes for our assets, we wrote our own md5 wrapper around the native crypto libraries, with approximately 30 lines of code.

Before, we used Perfect-XML to parse XML on Linux, as Foundation's XML parsing gave us strange crashes. In recent releases, these issues have been fixed, and we were able to drop the dependency and use Foundation instead.

On the client side, we slowly dropped more and more Javascript dependencies, until we were able to remove the entire Javascript build stack. There's no single application.js anymore, instead, we have a few inline scripts for pages that need it. For example, we ended up re-writing the payment form without React, which took about 150 lines of vanilla Javascript code. We maintained the spirit of the React-based code: our custom Javascript also keeps track of a state object and re-renders the potentially affected DOM nodes when the state changes.

We took a long hard look at the CSS, and also managed to remove almost all dependencies.

Taking stock after the refactoring, we cut down the CSS and Javascript sizes to a fraction of what they were before: the uncompressed CSS is 199KB, and there are only a few bits of inline Javascript. This makes for a faster site and โ€” at least in our case โ€” much happier developers ๐Ÿ˜€.

If you'd like to check out the backend, the source code is on GitHub.

Stay up-to-date with our newsletter or follow us on Twitter .

Back to the Blog

Recent Posts