Let's start with caching. So many levels of caching.
Before we even get to your website, there's DNS. What IP does your domain point to? Usually, your OS will cache this DNS lookup for you. Failing that, your DNS server—such as your ISP, 8.8.8.8, or 1.1.1.1—will. This isn't usually something you need to worry about as a web developer.
Next, the low-hanging fruit: CSS and JavaScript. These are easy to cache because the content is static and rarely changes. We can easily set HTTP headers through Nginx or Apache to cache these files for a long time.
But what about when the content does change? Can we afford to wait a week or a month before our customers' browsers pick up the new copy? Can we ask them to press Ctrl+F5? This isn't a good solution.
The easiest and most robust way to handle this is to change the actual filenames of the CSS and JavaScript files. If the filename changes, the browser will be forced to download a new copy.
Webpack can do this for you, but connecting the generated filenames to your server-side templating language is a little trickier. Generally, it boils down to using some kind of Webpack stats plugin to produce a JSON file listing all your assets. Your language of choice can then read this file and generate the necessary HTML. Not too bad.
Okay, but what about the HTML? Can we cache that too?
That gets even harder. Usually, HTML contains data—information that changes frequently. Even if we tried to cache it, how would we cache-bust it? Unlike CSS and JavaScript, we can't change the URL.
What if we removed all the data from the page and served only templates? The page could run an AJAX request to retrieve the data. Better yet, we could use a service worker so that our page loads even when offline. We could check for new resources in the background and either load them when the user returns or encourage them to refresh at their convenience.
What about the data, though? First, we have to wait for the initial page to load before we can even send our AJAX request. That's not cool. Maybe HTTP/2 push can help here.
Is it possible to cache the data? We can use IndexedDB to store a local copy and then synchronize updates with the server using Background Sync. But what about sensitive or shared data? We wouldn't want to send all our data to the client.
Even if we managed to send only the data they have access to, what would we do if their access were revoked? Too bad—all they have to do is turn off Wi-Fi, and they can keep using the app and accessing the data thanks to the PWA.
That's about all the client-side caching we can do. What about the server, though? Where does this data live? In a MySQL server? How long do those queries take? Can they be cached in memory?
What if two users request the exact same piece of information at the exact same time? Should we run the query twice? Can the queries be batched? What if one user makes many requests? Can we combine some of those HTTP requests? How do we know when the data becomes stale? Can we track mutations?
That's it for caching.
Now we have the perfect server setup. We've thought of everything, we have an infallible cache-busting strategy, and our payloads are under 14 KB—but our server just crashed.
Uh-oh! I hope you have automatic failover.
Serving static content from another server isn't too difficult, but data is trickier. Keeping all our database servers synchronized in real time is hard enough, but database writes are even harder.
There are also:
- Critical-path CSS
- 14 KB packets
- Optimizing JavaScript for performance and parse time, because size isn't the only thing that matters
- Moving JavaScript into Web Worker threads to avoid blocking the main UI thread
- Rewriting JavaScript in C and compiling it to WebAssembly
Be careful not to do too much interop with WebAssembly, or you'll negate the benefit. Passing data back and forth isn't free.
What about when your web app loses focus? Can we scale back some of the renders or network requests to play nicely?
These are just some of the things, off the top of my head, that we as web developers have to worry about when building a performant website in 2018.