Created
July 14, 2026 23:34
-
-
Save maiah/599be4017ce96190db1880b037f1dcc9 to your computer and use it in GitHub Desktop.
Astro Client Router with Cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| import { ClientRouter } from "astro:transitions"; | |
| --- | |
| <ClientRouter /> | |
| <script> | |
| import { pathCache } from "./path-cache"; | |
| document.addEventListener("astro:before-preparation", (ev) => { | |
| // 1. Grab the element from the event payload, or fallback to querying the DOM | |
| const anchor = | |
| (ev.sourceElement as HTMLElement) || | |
| document.querySelector(`a[href="${ev.to.pathname}"]`); | |
| const cacheKey = anchor?.dataset.astroCachePath || ev.to.pathname; | |
| console.log("========== astro:before-preparation triggered!!!", cacheKey); | |
| const cachedDocument = pathCache.get(cacheKey); | |
| if (cachedDocument) { | |
| console.log("======== cache hit"); | |
| ev.loader = async () => {}; | |
| } | |
| }); | |
| document.addEventListener("astro:before-swap", (ev) => { | |
| console.log("========== astro:before-swap triggered!!!"); | |
| console.log("ev.to:", ev.to); | |
| const anchor = document.querySelector( | |
| `a[href="${ev.to.pathname}"]`, | |
| ) as HTMLElement | null; | |
| const cacheKey = anchor?.dataset.astroCachePath || ev.to.pathname; | |
| const cachedDoc = pathCache.get(cacheKey); | |
| if (cachedDoc) { | |
| console.log("======== re-using cached document"); | |
| const newDoc = document.implementation.createHTMLDocument("New Document"); | |
| newDoc.replaceChild( | |
| cachedDoc.documentElement.cloneNode(true), | |
| newDoc.documentElement, | |
| ); | |
| ev.newDocument = newDoc; | |
| } else { | |
| console.log( | |
| "======== caching new document", | |
| ev.newDocument.body.firstChild, | |
| ); | |
| const newDoc = document.implementation.createHTMLDocument("New Document"); | |
| newDoc.replaceChild( | |
| ev.newDocument.documentElement.cloneNode(true), | |
| newDoc.documentElement, | |
| ); | |
| pathCache.save(cacheKey, newDoc); | |
| } | |
| }); | |
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class PathCache { | |
| private cache = new Map<string, Document>(); | |
| private tags = new Map<string, { id: string; document: Document }[]>(); | |
| get(path: string): Document | undefined { | |
| return this.cache.get(path); | |
| } | |
| save(path: string, document: Document) { | |
| this.cache.set(path, document); | |
| } | |
| saveTag(tag: string, id: string, document: Document) { | |
| const tagEntries = this.tags.get(tag) || []; | |
| tagEntries.push({ id, document }); | |
| this.tags.set(tag, tagEntries); | |
| } | |
| invalidate(path: string) { | |
| this.cache.delete(path); | |
| } | |
| invalidateTag(tag: string) { | |
| this.tags.delete(tag); | |
| } | |
| } | |
| export const pathCache = new PathCache(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment