From 1f0851518bbd6806c3db3472f9a81dfd69945089 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Mon, 5 Oct 2026 13:29:28 -0500 Subject: [PATCH 1/2] transitons + dev server improvements --- astro.config.ts | 12 ++++++++ patches/astro+5.18.2.patch | 21 +++++++++++++ .../CRETemplate/CRETemplateOverview.astro | 2 +- .../CRETemplate/CRETemplatePanel.astro | 2 +- .../CcipVersionToggle/CcipVersionGuard.astro | 2 +- .../ChangelogSnippet/ChangelogCard.astro | 2 +- .../CodeHighlightBlock.astro | 2 +- .../CodeHighlightBlockMulti.astro | 2 +- src/components/HeadCommon.astro | 4 +-- src/components/Header/Header.astro | 2 +- src/components/PageTabs.astro | 2 +- src/layouts/BaseLayout.astro | 30 ++++++++++++++++++- src/pages/certification.astro | 2 +- src/pages/cre-templates/index.astro | 2 +- src/pages/cre/[...id].astro | 2 ++ .../copyToClipboard/copyToClipboard.ts | 4 +-- src/scripts/fix-external-links.ts | 2 +- src/scripts/fix-remix-urls.ts | 2 +- src/scripts/scroll-to-search.ts | 2 +- tailwind.config.js | 13 +++++++- 20 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 patches/astro+5.18.2.patch diff --git a/astro.config.ts b/astro.config.ts index a9944ea59a8..361e9934eae 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -43,6 +43,18 @@ const canonicalUrlsWithLanguageVariants = extractCanonicalUrlsWithLanguageVarian export default defineConfig({ site: "https://docs.chain.link", trailingSlash: "never", + // Prefetch internal links so client-side navigations (ClientRouter) feel instant. + // "hover" (not "viewport") avoids prefetching the hundreds of links in the docs sidebar at once. + // + // NOTE (Astro 5 -> 7 upgrade): `prefetch` and `` are stable in Astro 5 and remain + // the supported API in Astro 6/7, so this config carries over unchanged. The one thing to revisit + // is `patches/astro+5.18.2.patch` (dev-server module-graph perf fix): it is pinned to 5.18.2 and + // will fail to apply after the upgrade. Check whether the upstream fix has landed by then; if not, + // regenerate the patch against the new version with `npx patch-package astro`. + prefetch: { + prefetchAll: true, + defaultStrategy: "hover", + }, redirects: { "/ccip/directory": "/ccip/directory/mainnet", "/ccip/supported-networks": "/ccip/directory/mainnet", diff --git a/patches/astro+5.18.2.patch b/patches/astro+5.18.2.patch new file mode 100644 index 00000000000..2326c547f7f --- /dev/null +++ b/patches/astro+5.18.2.patch @@ -0,0 +1,21 @@ +diff --git a/node_modules/astro/dist/vite-plugin-astro-server/vite.js b/node_modules/astro/dist/vite-plugin-astro-server/vite.js +index 81bb5cf..e2f060c 100644 +--- a/node_modules/astro/dist/vite-plugin-astro-server/vite.js ++++ b/node_modules/astro/dist/vite-plugin-astro-server/vite.js +@@ -60,6 +60,16 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne + } + } + function isImportedBy(parent, entry) { ++ // Vite 6's backward-compatible ModuleNode rebuilds a union Set (and looks up a compat ++ // node for every importer) each time `importers` is read. With ~3.7k icons importing ++ // one module that is ~27M iterations per request. Read the per-environment Sets directly. ++ const client = entry._clientModule; ++ const ssr = entry._ssrModule; ++ if (client || ssr) { ++ if (client) for (const importer of client.importers) if (importer.id === parent) return true; ++ if (ssr) for (const importer of ssr.importers) if (importer.id === parent) return true; ++ return false; ++ } + for (const importer of entry.importers) { + if (importer.id === parent) { + return true; diff --git a/src/components/CRETemplate/CRETemplateOverview.astro b/src/components/CRETemplate/CRETemplateOverview.astro index cd4f5a7db78..a408b5268c2 100644 --- a/src/components/CRETemplate/CRETemplateOverview.astro +++ b/src/components/CRETemplate/CRETemplateOverview.astro @@ -80,7 +80,7 @@ const { frontmatter } = Astro.props - diff --git a/src/components/PageTabs.astro b/src/components/PageTabs.astro index 12ff4ad2696..3bb224b02d6 100644 --- a/src/components/PageTabs.astro +++ b/src/components/PageTabs.astro @@ -466,7 +466,7 @@ const displayPage = hasActivePage ? (Array.isArray(currentPageGroup) ? currentPa }) } - window.addEventListener("load", initDropdown) + document.addEventListener("astro:page-load", initDropdown) // Update padding based on header visibility const section = document.querySelector(".tabs-section") as HTMLElement diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 4974f73342e..b0b76034b93 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,4 +1,5 @@ --- +import { ClientRouter } from "astro:transitions" import HeadCommon from "~/components/HeadCommon.astro" import HeadSEO from "~/components/HeadSEO.astro" import StructuredData from "~/components/StructuredData.astro" @@ -27,6 +28,7 @@ const canonicalURL = new URL(canonicalURLStr) + - +
diff --git a/src/pages/certification.astro b/src/pages/certification.astro index dee853fb942..bc53e42e530 100644 --- a/src/pages/certification.astro +++ b/src/pages/certification.astro @@ -835,7 +835,7 @@ const formattedContentTitle = `Courses | Chainlink Certifications` diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index b0b76034b93..e2094bdb58c 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -4,6 +4,7 @@ import HeadCommon from "~/components/HeadCommon.astro" import HeadSEO from "~/components/HeadSEO.astro" import StructuredData from "~/components/StructuredData.astro" import Header from "~/components/Header/Header.astro" +import NavigationProgress from "~/components/NavigationProgress.astro" import { NewsletterCTA } from "~/components/Footer/NewsletterCTA" import Footer from "~/components/Footer/Footer.astro" import { Metadata, QuickstartsFrontmatter } from "~/content.config.ts" @@ -66,6 +67,47 @@ const canonicalURL = new URL(canonicalURLStr) + +
diff --git a/src/pages/cre/[...id].astro b/src/pages/cre/[...id].astro index 4744e75750d..24f7922759a 100644 --- a/src/pages/cre/[...id].astro +++ b/src/pages/cre/[...id].astro @@ -125,6 +125,21 @@ if (isCanonical) { {isCanonical && } + { + // Marker read by BaseLayout's astro:before-swap handler. A canonical CRE page renders an + // empty body and redirects to the language-specific URL; client-side routing would swap in + // that empty body and flash before the redirect runs. The handler cancels the swap and does + // a full navigation instead, so the redirect happens before first paint. + isCanonical && ( + + ) + } + { isCanonical && (