Uber.com is like no website I’ve ever worked on in my past. It touched every line of business at Uber, it had over 4 million pages, and was translated in 50 languages. The start of this project was difficult for me on so many levels. In my previous experiences, I’ve always worked on behalf of an agency and this is important because agencies rarely get the opportunity to work on higher level projects like web performance. So when being tasked by my boss, to focus on the performance for uber.com, I started extremely lost on what was expected of me. Over the next year, I set and iterated on a few goals that led me to success. In this writeup we’ll be covering three major topics: All that went into to running and maintaining uber.com. My larger contributions to uber.com. How my contributions lead me to being successful at uber.
Who & What is Uber.com
Technology & Architecture
Content Management Systems
Testing and Monitoring
Who is Uber.com
What is Ubercom
Translated in over 50+ languages
Technology & Architecture
Uber.com technology is seriously the largest bowl of buzzword soup I’ve had the pleasure to eat. In respect to time, I won’t beable to explain the entirety of the Architecture but only feed you small spoonfuls.
- HTTP / RPC
- All Purpose Programming
- Templating & Styling
- Isomorphic Koa
- Dependency Injection
- SSR React
- State Manager
- Atomic CSS
- Block CMS
- i18n Integration
- JSON Schema
- Marketing Site
- A/B Testing
- Edge Caching
- Media Hosting
- Media Optimizations
The Block System
Uber.com was made of many small components. We composed together into what we called “Blocks”. Blocks are simply a composition of components and a Schema file. Below is a deep dive into the more than 160 Blocks that make up uber.com.
Content Management System
Being a global company Uber.com had a very tight workflow for translations. Translations were kicked off through Chameleon and within a week or so a page could be translated in over 50 languages.
Updating uber.com was pretty tedious. It required 3 sequential code reviews across the three repositories: components, CMS, sites. Landing code on to master ran through continuous integration to run unit tests, type checking and linting.
Visual Regression Testing
Automated E2E Testing
A base FusionJS app is roughly 60kbs and our app was a whooping 1.2mbs this gave me a the confidence to set a pretty straightforward goal: - 50% reduction in JS Bundle The bundle size of uber.com kept growing deployment after deployment. Before my first optimization our bundle had reached 1.2mbs! At the time, I knew that I was no performance engineer and 50% bundle reduction was an aggressive goal. That said, I’ve never in my life worked on a marketing website that had such an enormous bundle size.
Bundling, transpiling, & module systems.
Image Processing with Lazy loading
Our first optimization was to leverage a service Cloudinary. Cloudinary has some killer features that can make image optimization a breeze. Cloudinary is a file storage cdn with a graphic service layer in front. I like to describe it as “Photoshop in the cloud!” Let’s take this first example image on the current homepage of uber.com.
Each field above could be improved. Starting with dimensions, imagine that the user is viewing the website from a WXGA (1366x768) resolution, our image’s dimension would be unnecessarily large. Cloudinary offers width and height flags that you pass in the img src url.
A JPG file type is pretty optimized relative to png and gif; however, webp is a well supported image format that’s compression is superior to jpg.
Well so far so good, but we can do better! Let’s talk about image quality/compression. Inside cloudinary there are tons of things you can do. The example to the left makes quality extremely low and therefore you can see the artificating. however, best and simplest is a flag `q_auto:eco`.
Finally using Intersection Observer I was able to decrese initial page download by 40% by lazyloading images that exsisted below the users viewport.
Full HTTP/2 Support All of our JS and images were served on cloudfront edge over HTTP2. That said there were dozens of resources still coming from origin that were HTTP1.1. I admittedly didn’t do this work; however, I had to work with Infra at Uber for over a year to get this deployed into production. It is difficult to measure the performance here but statistics say that there can be up to a 30% decrease in network latency going fromHTTP1.1 to HTTP2. L2 Edge Caching Uber.com has over 4 million pages and to build these pages it relys on dozens of 3rd party services for content, localization, and geolocation etc. Each one of these at any time could go down and potentially take down pages of our website. GCP caching is amazing because it will cache responses from origin and put them on the edge. That said implementing GCP caching comes with a bunch of gotchas. The biggest of which is that your server cannot use Set-Cookie in the response headers otherwise GCP will ignore it as a cache key. I implemented GCP caching on www.uber.com/airports. GCP caching reduced our Time to first Byte (TTFB) by 1.2s.
For nearly six months I focused most of my effort on performance of uber.com. In then end, I was able to results my own expectations! - 50% reduction in Page Download - 50% reduction in JS Bundle - 50% reduction in TTFB - 50% reduction in TTI