With the arrival of HTTP/2 (RFC 7540 published on May 15, 2015) and the performance changes it introduces, there have been some misleading information about which optimization techniques are anti-patterns and therefore should be removed and which ones we should keep.
Let's review the techniques HTTP/2 is impacting the most and where a change is advised:
Popular optimization techniques like concatenation of JS/CSS files and image spriting aim to reduce the HTTP protocol overhead and network latency by building assets into a single response. HTTP/1.x limited parallelism and high protocol overhead made these techniques critical for performance improvement. HTTP/2 provides support for request and response multiplexing (see Figure 1), which means that we can now optimize our applications by delivering more granular resources while making better use of HTTP cache. Also HTTP/2 introduces header compression which dramatically reduces the metadata overhead of each HTTP request.
Figure 1. HTTP/2 multiplexing
That being said, HTTP/2 does not eliminate the benefits of concatenation and spriting completely; consider the following:
- Files that contain similar data may achieve better compression when bundled.
- Each resource request carries some overhead, both when reading from cache (I/O requests), and from the network (I/O requests, on-the-wire metadata, and server processing).
Another well-known optimization is resource inlining, that reduce the number of HTTP requests by embedding the resource within the document itself (e.g. embedding an small image into an HTML document via a data URI). HTTP/2 brings a feature called Server Push where the server is able to proactively push data without the client requesting it. There is no longer a reason to inline resources just because they are small; we’re no longer constrained by the lack of parallelism and the request overhead is very low.
Critical resources that block page construction and rendering (like JS and CSS) are good candidates for server push as illustrated in Figure 2.
Figure 2. Server push
Domain Sharding is a powerful technique that split resources across multiple domains to overcome a limitation imposed by browsers where they can only make an average of 6 parallel connections per domain. When multiple domains are used, browsers are able to download more resources simultaneously, resulting in a faster user experience.
HTTP/2 allows requests multiplexing over the same TCP connection as shown in Figure 1 above, which enables effective request and response prioritization, flow control, and header compression.
As a result, the optimal number of connections is exactly one and domain sharding is an anti-pattern.
However, due to third-party dependencies it may not be possible to fetch all the resources via the same TCP connection.
According to HTTP Archive, the average number of requests to the same domain is 52, so consider old browser versions where HTTP/2 is not supported and domain sharding is a good candidate, specially if your site is doing multiple requests to the same domain.
Convert Import to links is another optimization used to reduce load time for CSS files. Using @import within a stylesheet adds one more roundtrip to the overall download time of the page. For old versions of Internet Explorer, @import causes the download order to be altered, this may cause stylesheets to take longer to download.
Using link ensures that stylesheets will be downloaded in parallel across all browsers.
Servers that support HTTP/2 Push can intelligently read <link> tags and preemptively push dependencies, resulting in very fast load times and eliminating the need for file concatenation in case of HTML imports.
HTTP/2 introduces great changes in terms of performance, some of those changes might replace a few of the existing optimization techniques in most cases but not always, as we saw; there are some considerations to keep in mind and you must examine the particularities of your site before deciding to remove them.