Skip to content

Instantly share code, notes, and snippets.

@cerebrl
Last active December 18, 2020 08:14
Show Gist options
  • Save cerebrl/2580c3fbd0dd50f8e5203901ce194dec to your computer and use it in GitHub Desktop.
Save cerebrl/2580c3fbd0dd50f8e5203901ce194dec to your computer and use it in GitHub Desktop.
Answering a friend's question in Slack

High Performance Web Apps for HTTP 1.1

Question:

Is anyone aware of bottlenecks when code splitting in HTTP 1.1? Perhaps better put: is there a point of diminishing return in terms of bundle sizes and network calls.

In other words: Is it better to request 5 x 200kb requests or 10 x 100kb files?

Given that http 1.1 caps at 6 requests per one origin in chrome, and 10 total, I’m curious if the 5 extra network requests above are going to negatively impact performance in terms of initial loads.

Answer:

Since HTTP 1.1 has been around for a long while, I’d say the industry has already decided what the best architecture is for optimal network performance [1], and, if I remember correctly:

  1. Minimize the overall number of resources requested to as few as possible, so 5 x 200kb files is better than 10 x 100kb files
  2. Minimize the overall size of the requested resources (5 x 150kb files is better than 5 x 200kb files)
  3. Minimize the both the size and number for critical path [2], so 2 x 150kb files initially, and then lazy load the remaining 3 x 200kb files
  4. Shorten the physical distance to the user by serving as much from a CDN as possible
  5. Use multiple origins to parallelize resource downloading (aka domain sharding [3]).

So, to achieve (1) above, it’s bundle everything of likeness together: JavaScript with Webpack (or Rollup, etc.), images as sprites, icons as fonts or SVGs, CSS for style … Use compression for everything: WebP for images, gzip, minimize … addressing (2). Then, “split” the bundles for the critical path from non-critical path, addressing (3). Critical path bundles is loaded with priority and anything non-critical is delayed or lazy-loaded for (3).

It’s also important to remember that your JS resources are competing with all your other resources, both in total and per origin, That’s fonts, images, CSS, videos … so splitting your JS (if splitting just into chunks and not splitting by route or page) adds to the competition with all the other resources. Placing them on CDNs helps distance (4), and using different origins helps the competition (5), so images.mysite.com, styles.mysite.com, scripts.mysite.com.

Once you address the general “basics” of network performance from above, it starts to get much more contextual.

Let’s talk about context:

  1. are your users mostly mobile users (offline capability for mobile network instability and latency)
  2. are your users mostly return users or first-time (cache versus non-cached resources)
  3. are your users mostly rural, city, personal or business (network quality, device quality … )
  4. are your users resources mostly images, code, videos, CSS, HTML … (where to invest the effort)
  5. are the resources lots of small things, or a few large things … (bundling or compressing)
  6. are you leveraging prefetching … (start the HTTP handshakes before you need them)
  7. are you sending precompiled HTML from a CDN to render (like a JAM Stack) … (reduce script execution time)
  8. is your site/app already PWA with local caching via service workers?

After considering the above questions from a contextual/qualitative point of view, it’s now time to do some quantitative measuring. Most performance-network engineers will recommend using measurements from your live site/app with real user data to measure the problems both engineering and business. Don't guess what your problem is, or just solve something becuase it's interesting.

Strategy

If you want to ensure your engineering strategy is also a good business strategy (and you do), you want to answer these questions:

  1. Where/what is the biggest loss of performance? What metric will you use to measure it?
  2. What’s the desired business outcome of this effort? What metric will you use to measure it?
  3. What level of effort/cost will be required to both improve the performance and improve the business outcome?
  4. What is a realistic outcome for both engineering and business?
  5. What is your resource budget?

Here’s an example of a good strategy (example answers to above questions):

  1. Multiple, large product images per page load; total kb of image data required
  2. Low sales on product pages; increase conversion rate of visits to sales
  3. Four sprints worth of work by two product teams
  4. Decrease total page image data by one third (engineering goal) will result in 25% increase is conversion rate (business goal)
  5. Five sprints worth of work by two product teams

With this strategy, you have a tangible problem that's measurable. You have a realistic, measurable business problem. You know what it will take to fix it and what success looks like. Finally, you can do it within the given budget.

Here’s an example of a bad strategy:

  1. Mobile latency for rural users is too slow; number of phones distributed with preloaded images
  2. More sales of product; increase conversion rate of visit to sales
  3. $1,000,000 to pay Verizon to put preloaded images on phones
  4. Delegate work to Verizon to make 5% of our users happier
  5. A sprint with two engineers

The point of the absurd, “bad” strategy above is simple: don’t put effort into something that isn’t a problem within your control, isn’t measurable, isn’t addressing a business need, won’t result in a practical outcome or is too costly compared to the business value.

Don't just trust me

With that said, I’m not a network-performance engineer. But, I know a thing or two about the intersection of engineering and business. Most of what I learned in this area of engineering, I learned originally from Steve Souders from Google, and then later from Ilya Grigorik. Ilya’s the network performance engineer and a developer advocate at Google. Here’s his presentation deck I’m most familiar with. He and his team are quite involved in the community, so reaching out to him/them might be beneficial.

There’s also Alex Sexton (an Austin local that’s quite famous in the JavaScript scene). He did a lot of perf optimization while he was at Bizarre Voice (now at Stripe). I’m sure Netflix will have some interesting developers addressing network performance. Oh, and Paul Lewis, another Google Engineer, and Addy Osmani are probably a good resources too.

Good luck! And as with all science, make sure it is measurable, falsifiable and reproducible.

Footnotes

  1. This is “old-school” HTTP/1 advice and is, at times, counter to HTTP/2 networking performance
  2. Critical path: the time to the availability of high priority interactions of the UI
  3. Domain sharding on the modern web - JP - Medium
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment