Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 2 min read

Reuse a Cached App Shell Without Blurring Query-Driven Responses

A cached app shell may fail to load offline when a navigation adds a tracking or cosmetic query parameter. A request for /app and one for /app?utm_source=newsletter are different URLs under default cache matching, even w

A cached app shell may fail to load offline when a navigation adds a tracking or cosmetic query parameter. A request for /app and one for /app?utm_source=newsletter are different URLs under default cache matching, even when both should receive the same shell document.

The safe fix is route-scoped rather than global. First classify the request: allow only GET requests for a canonical shell path such as /app. For that one lane, use a cache lookup that ignores the URL search component. The cached shell can then satisfy navigations with campaign tags or other parameters that do not alter the shell response. The request still carries its full URL; only cache comparison changes.

Leave every other request on exact matching. API endpoints, searches, filtered results, user profiles, reports, and locale-specific content often use query parameters to select the response. In those cases, ignoring search could make one request receive a response intended for another query. Non-GET requests should bypass this shell-cache policy and continue to the network.

Expected behavior is intentionally limited. Two shell navigations with harmlessly different query strings can use one cached shell entry. If that entry is absent, the request falls back to the network. A query-sensitive request remains keyed by its complete URL and cannot select another query’s cached response.

Keep the decision function separate from service-worker event wiring. A controlled fixture can verify that application code selects the intended lookup option, preserves exact matching elsewhere, and bypasses non-GET requests. It cannot prove browser Cache API behavior, secure-context requirements, or the service-worker lifecycle; those require browser integration verification.

Ignoring search does not normalize different paths, reorder parameters, or establish a caching strategy for every route. Use it only where the path identifies a reusable shell and the search string does not change what that response means.

Working example

// This module contains no service-worker side effects on import.
// Proof boundary: the route selection below is application code. A real browser
// service worker is still required to prove Cache.match()'s own cache semantics.

export const APP_SHELL_PATH = "/app";

export function isAppShellRequest(request) {
  const url = new URL(request.url);
  return request.method === "GET" && url.pathname === APP_SHELL_PATH;
}

/**
 * Handles an already-intercepted service-worker fetch request.
 *
 * Only GET requests are eligible for cache lookup. Within that set, only the
 * chosen app-shell route ignores its query string; API endpoints and other
 * query-driven routes use Cache.match()'s default exact matching.
 */
export async function handleAppShellFetch(request, { cache, networkFetch }) {
  // Cache.match() normally only matches GET and HEAD requests, but this policy
  // intentionally does not involve the cache for any non-GET operation.
  if (request.method !== "GET") {
    return networkFetch(request);
  }

  const cached = isAppShellRequest(request)
    ? await cache.match(request, { ignoreSearch: true })
    : await cache.match(request);

  return cached ?? networkFetch(request);
}

/**
 * Optional service-worker wiring. Call this from the service-worker script
 * after opening the intended Cache instance.
 */
export function registerAppShellFetchHandler(scope, dependencies) {
  scope.addEventListener("fetch", (event) => {
    event.respondWith(handleAppShellFetch(event.request, dependencies));
  });
}

Read the full article: https://chriseugenerodriguez.com/blog/cache-match-ignore-search-app-shell

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.