Getting content over the Web is slow and expensive. Large responses require multiple round-trips between the client and server, which delays the browser’s acquisition and processing of content and increases traffic costs for visitors. Therefore, the ability to cache and reuse previously acquired resources becomes a key aspect of performance optimization.
The good news is that every browser comes with its own HTTP caching implementation. You just need to make sure that each server response provides the correct HTTP header directive to indicate when the browser can cache the response and for how long.
Note: If you use Webview to fetch and display web content in your application, you may need to provide additional configuration flags to ensure that HTTP caching is enabled, that its size is set appropriately for the use case, and that the cache is persistent. Be sure to check the platform documentation and confirm your Settings!
When the server returns a response, it also issues a set of HTTP headers that describe the response’s content type, length, cache directive, authentication token, and so on. For example, in the interaction above, the server returns a 1024-byte response, instructs the client to cache it for up to 120 seconds, and provides a validation token (” X234DFF “) that can be used to check if the resource has been modified after the response expires.
The cached response is validated against the ETag
- The server passes the authentication token using the ETag HTTP header.
- Validation tokens enable efficient checking of resource updates: no data is transmitted when the resource has not changed.
Suppose the browser makes a new request for the resource 120 seconds after it was first obtained. First, the browser checks the local cache and finds the previous response. Unfortunately, this response has now expired and the browser is not available. At this point, the browser can directly issue a new request and get a new full response. However, this is less efficient, because if the resource hasn’t changed, it makes no sense to download the exact same information that is already in the cache!
This is exactly what the validation token (specified in the ETag header) is designed to solve. The random token that the server generates and returns is usually a hash of the contents of the file or some other fingerprint. The client doesn’t need to know how the fingerprint was generated, just send it to the server on the next request. If the fingerprint remains the same, the resource has not changed and you can skip the download.
In the above example, the client automatically provides the ETag token within the “if-none-match” HTTP request header. The server checks the token against the current resource. If it does Not change, the server returns a 304 Not Modified response, telling the browser that the response in the cache has Not changed and can be delayed for another 120 seconds. Note that you do not have to download the response again, which saves time and bandwidth.
As a web developer, how can you take advantage of efficient revalidation? The browser does all the work for us: it automatically detects whether an authentication token was specified, it appends the authentication token to the request that was issued, and it updates the cache timestamp if necessary based on the response it receives from the server. The only thing we need to do is make sure the server provides the necessary ETag tokens. Check your server documentation for the necessary configuration flags.
Tip: The HTML5 Boilerplate project contains sample configuration files for all the most popular servers, with detailed annotations for each configuration flag and setting. Find your favorite server in the list, look for the appropriate Settings, and then copy/confirm that your server is configured with the recommended Settings.
Cache-Control
- Each resource can define its caching policy through the cache-Control HTTP header
- The cache-control directive controls who can Cache responses under what conditions and for how long.
From a performance tuning point of view, the best requests are those that do not require communication with the server: you can eliminate all network latency with a local copy of the response, as well as avoid traffic charges for data transfer. To achieve this, the HTTP specification allows the server to return cache-control directives, which Control how and for how long the browser and other intermediate caches Cache each response.
The cache-control header is defined in the HTTP/1.1 specification, replacing the previous header (such as Expires) used to define the response caching policy. All modern browsers support cache-control, so it is sufficient to use it.
-
“No-cache” and “no-store” “no-cache” indicates that you must check with the server to see if the response has changed before you can use the response to satisfy subsequent requests for the same url. Therefore, no-cache initiates a round-trip communication to verify the cached response if the appropriate authentication token (ETag) is present, but avoids the download if the resource has not changed. “No-store,” by contrast, is much simpler. It directly prohibits the browser and all intermediate caches from storing any version of the return response, for example, that contains personal privacy data or banking data. Each time a user requests the asset, the request is sent to the server and the complete response is downloaded.
-
If a response is marked as “public,” the response can be cached even if it has associated HTTP authentication and even if the response status code generally cannot be cached. In most cases, “public” is not required because explicit cache information (such as “max-age”) already indicates that the response can be cached. In contrast, browsers can cache “private” responses. However, these responses are typically cached only for a single user, so no intermediate cache is allowed to cache them. For example, a user’s browser can cache an HTML web page that contains a user’s personal information, but a CDN cannot.
-
The “max-age” directive specifies the maximum time (in seconds) that the obtained response is allowed to be reused, starting from the time of the request. For example, “max-age=60” means that the response can be cached and reused for the next 60 seconds.
Define the optimal cache-control policy
Follow the above decision tree to determine the best caching strategy for a particular resource or set of resources used by your application. Ideally, your goal should be to cache as many responses as possible on the client, for as long as possible, and to provide an authentication token for each response for efficient revalidation.
Cache-Control | Instructions and instructions |
---|---|
max-age=86400 | The browser and any intermediate cache can cache the response (if it is a “public” response) for up to 1 day (60 seconds x 60 minutes x 24 hours). |
private, max-age=600 | The client’s browser can only cache the response for up to 10 minutes (60 seconds x 10 minutes). |
no-store | The response is not allowed to be cached and must be obtained in full on each request. |
According to HTTP Archive, of the top 300,000 ranked sites (as ranked by Alexa), almost half of all downloaded responses can be cached by the browser, which can significantly reduce repetitive web browsing and visits. Of course, this does not mean that 50% of your specific application’s resources can be cached. Some sites can cache more than 90% of their resources, while others may have a lot of private or time-sensitive data that cannot be cached at all.
Review your web pages to determine which resources can be cached and make sure they return the correct cache-Control and ETag headers.
Deprecate and update cached responses
- The locally cached response is used until the resource “expires.”
- You can force the client to update to the new version of the response by embedding a file content fingerprint in the url.
- For best performance, each application needs to define its own cache hierarchy.
Client caching and quick updates? You can change the url of a resource when its content changes, forcing users to download a new response. Typically, this can be done by embedding the fingerprint or version number of the file in the file name – for example style.x234dff.css.
Cache checklist
There is no optimal caching policy. You need to define and configure the appropriate Settings for each resource, as well as the overall “cache hierarchy,” based on the communication pattern, the type of data provided, and the specific data update requirements applied.
Here are some tips and methods to keep in mind when developing a caching strategy:
-
Use consistent Urls If you offer the same content on different urls, you will get and store that content multiple times. Tip: Note that urls are case sensitive.
-
Make sure the server provides an authentication token (ETag) With an authentication token, there is no need to pass the same bytes when the resource on the server has not changed.
-
Determine which resources can be cached by intermediate caches Resources that respond identically to all users are well suited for caching by CDN and other intermediate caches.
-
Determine the best cache cycle for each resource Different resources may have different update requirements. Review and determine the appropriate max-age for each resource.
-
Determine the cache hierarchy that works best for your site You can control the speed at which clients get updates by combining resource urls that contain content fingerprints with short or no-cache cycles for HTML documents.
-
Minimize agitation when some resources are updated more frequently than others. If a particular part of a resource (such as JavaScript functions or CSS style sets) is updated frequently, consider providing its code as a separate file. This way, each time an update is fetched, the rest of the content (such as content library code that changes less frequently) can be fetched from the cache, minimizing the size of the download.
Open the page | IE6 (httpwatch) | FF3.5 (httpfox) |
---|---|---|
1. Open the page for the first time | 200 | 200 |
2. Restart the browser and open the page | Cache. Resource changes are not rerequested even when they occur | Cache. Resource changes are not rerequested even when they occur |
3. F5 to refresh | 304: The modified resource status is 200 | 304: The modified resource status is 200 |
4. Ctrl + F5 to refresh | 200, forcing a new request | 200 |
5. The back | Cache, simply load directly from the cache | Cache, simply load directly from the cache |
6. In the address box of the accessed page, press Enter | cache | cache |