DEV Community

Arthur031221
Arthur031221

Posted on

Why a missing JavaScript file can stay missing after you deploy it

cachewhy local response demo

I built cachewhy around a small but costly HTTP cache mistake. Imagine a request for /missing.js that returns 404 with Cache-Control: public, max-age=2678400. That lifetime is 31 days. A browser may reuse the missing response even after the file is deployed. Changing the server header helps new responses, but it does not automatically erase a copy the browser already holds.

The command fetches a URL and explains the response that came back. It prints one row for a private browser cache and one for a shared cache, along with the header that drove the result. It follows redirects with a bound and cancels the response body after reading headers. The local fixture in the repository serves both the long lived 404 and a new response with no-store.

npx --yes github:Arthur031221/cachewhy https://example.com
Enter fullscreen mode Exit fullscreen mode

The report uses http-cache-semantics for storage and freshness calculations, then accounts for Age, Date, and request delay. It distinguishes no-store from no-cache: the former prevents storing a new response, while the latter allows storage but requires validation before reuse. s-maxage changes the shared cache row. An ETag or Last-Modified value can help with revalidation once a response is stale.

A remote probe has important limits. It cannot tell what is already in a particular browser's cache, whether a service worker intercepts the request, which cache key a CDN chose, or whether a provider rule overrides the visible headers. A CDN might serve the probe from its own cache. The output is a reading of the response received now, not a replay of every user's experience.

I included tests for a cached 404, no-store, private responses, s-maxage, Age, stale revalidation, redirects, and timeouts. The fixture makes the main failure visible without depending on a live website. It is useful for debugging a specific URL and for attaching a compact explanation to an issue.

The repository is MIT licensed: https://github.com/Arthur031221/cachewhy. I would value examples of real response headers where the explanation is too terse or reaches beyond what those headers establish.

Top comments (2)

Collapse
 
launchgatecheck profile image
Launch Gate •

The limit you call out about an existing browser cache is important. A useful companion to the fixture would be a two-stage browser test: request the long-lived 404, switch the same URL to 200/no-store, then compare an ordinary repeat request in that profile with a fresh profile and the CLI probe. Keep service workers out of the fixture and record whether each request reached the origin. That would show why a clean report for the current 200 doesn't establish that a returning user's cached 404 is gone. Does the output already distinguish "this response must not be stored" from any claim about earlier stored responses?

Collapse
 
arthur031221 profile image
Arthur031221 •

Thanks, that is a useful distinction. The output labels a current no-store response as not storable, and it does not claim to remove or invalidate a response already stored by a browser. The fixture currently demonstrates the server responses through the CLI, not a two-stage browser test. I would add your same-profile and fresh-profile comparison with origin request logging to show whether the repeat request reaches the server.