perf: avoid structuredClone in sidebar generation for prerendered builds#3761
perf: avoid structuredClone in sidebar generation for prerendered builds#3761MohamedH1998 wants to merge 1 commit intowithastro:mainfrom
Conversation
✅ Deploy Preview for astro-starlight ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
🦋 Changeset detectedLatest commit: 29f745a The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Hello! Thank you for opening your first PR to Starlight! ✨ Here’s what will happen next:
|
There was a problem hiding this comment.
Thanks for the PR @MohamedH1998!
I have a feeling this is maybe adding much more code than necessary unless I misunderstood something. Could you explain why you needed the additional findAndMarkCurrentEntry() function (which is basically identical to the existing setIntermediateSidebarCurrentEntry()) and the separate getSidebarRender() function?
IIUC the sidebar could use identical code in prerendered and on-demand builds, with the only difference being that when prerendering, it’s safe to skip the structured clone. Does that sound right to you? If so, the changes can probably be much more minimal.
Inspired by #3761 but with an implementation that is closer to the existing architecture and avoids some unnecessary code duplication.
|
@MohamedH1998 I opened an alternative approach to removing Would you be able to test it on your Cloudflare Docs branch to see how it performs? You can install a preview release with: pnpm add https://pkg.pr.new/@astrojs/starlight@3768 |
|
@delucis FYI, we've bumped our starlight version and saw the same improvements! Appreciate you getting it sorted so quickly |
|
Awesome, thanks for letting us know! |

Description
During prerendered builds,
generateRouteDatawas callinggetSidebaron every page, which does a fullstructuredCloneof the intermediate sidebar tree on each call. For large sites this is O(n) allocations × number of pages (in our case 7303 page).This PR introduces a fast path
getSidebarForRender— that mutates the shared intermediate sidebar in place by flipping a singleisCurrentpointer per call, reducing sidebar work to O(1) per page during static builds.As a POC, I've implemented a patch to the package in our repo which saw a significant decrease in build times, see here
Changes
utils/navigation.ts
getSidebarForRender: mutates the cached intermediate sidebar in place, tracking the previously-current link per locale so it can be reset on the next call without a full tree scan.resetCurrentEntries: ensures the clone path (getSidebar/getSidebarFromConfig) always starts from a clean state, guarding against staleisCurrentflags if the intermediate cache was previously mutated by the fast path.findAndMarkCurrentEntry: shared helper for the in-place mutation path.utils/routing/data.ts
config.prerenderingenerateRouteData: usegetSidebarForRenderfor static builds,getSidebarfor SSR.structuredClonethe result ofgetSidebarForRenderbefore handing it off to the route data object, so each page's sidebar snapshot is isolated from subsequent mutations.relevant tests