Improve API docs build performance and reduce build invalidation#601
Improve API docs build performance and reduce build invalidation#601IEvangelist merged 2 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR targets an API docs build regression by reducing repeated work during Astro API page generation and trimming overly-broad build inputs, especially for sidebars and docs includes.
Changes:
- Memoizes
packages/tsModulescollection loads and API sidebar generation in production builds. - Scopes C# and TypeScript API sidebars to the current package/module for most API pages (instead of building the full catalog per page).
- Makes
write-git-env.mjsdeterministic and avoids rewriting.env.localwhen content hasn’t changed; replaces docs-wide eager globbing inInclude.astrowith a targeted docs collection lookup.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/frontend/src/utils/ts-modules.ts | Memoizes TypeScript module collection loads in production and applies minor formatting cleanups. |
| src/frontend/src/utils/ts-api-sidebar.ts | Adds production memoization and supports building a sidebar scoped to a specific TS package/module. |
| src/frontend/src/utils/packages.ts | Memoizes package collection loads in production and applies minor formatting cleanups. |
| src/frontend/src/utils/api-sidebar.ts | Adds production memoization and supports building a sidebar scoped to a specific C# package; includes small sidebar micro-optimizations. |
| src/frontend/src/pages/reference/api/typescript/[module]/index.astro | Uses a package-scoped TS sidebar instead of the full-catalog sidebar. |
| src/frontend/src/pages/reference/api/typescript/[module]/[item]/index.astro | Uses a package-scoped TS sidebar instead of the full-catalog sidebar. |
| src/frontend/src/pages/reference/api/typescript/[module]/[item]/[member]/index.astro | Uses a package-scoped TS sidebar instead of the full-catalog sidebar. |
| src/frontend/src/pages/reference/api/csharp/[package]/index.astro | Uses a package-scoped C# sidebar instead of the full-catalog sidebar. |
| src/frontend/src/pages/reference/api/csharp/[package]/[type]/index.astro | Uses a package-scoped C# sidebar instead of the full-catalog sidebar. |
| src/frontend/src/pages/reference/api/csharp/[package]/[type]/[memberKind].astro | Uses a package-scoped C# sidebar instead of the full-catalog sidebar. |
| src/frontend/src/components/Include.astro | Replaces eager docs-wide globbing with getEntry('docs', ...) + render(...) for targeted includes. |
| src/frontend/scripts/write-git-env.mjs | Uses CI-provided commit SHA or git rev-parse HEAD, and avoids rewriting .env.local unless values change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| // Resolve the include through the docs collection instead of eagerly globbing | ||
| // the entire docs tree into every page that uses <Include>. |
There was a problem hiding this comment.
What does this comment mean? Why is it saying "instead of eagerly globbing the entire docs tree"?
There was a problem hiding this comment.
The code before, was doing this:
...(import.meta.glob('/src/content/docs/**/*.md', { eager: true }) as Record<string, unknown>),
...(import.meta.glob('/src/content/docs/**/*.mdx', { eager: true }) as Record<string, unknown>),
Which eagerly enumerated ALL matching .md and .mdx files. Which was not good for perf.
| import { getCollection } from 'astro:content'; | ||
|
|
||
| let packagesPromise: Promise<any[]> | undefined; | ||
| const shouldCachePackages = import.meta.env.PROD; |
There was a problem hiding this comment.
Why change the behavior on PROD?
There was a problem hiding this comment.
Locally, during dev, if we have a cached version - it's less of a concern. On PROD, we want to ensure we build from the latest regardless.
| import { getCollection } from 'astro:content'; | ||
|
|
||
| let tsModulesPromise: Promise<any[]> | undefined; | ||
| const shouldCacheTsModules = import.meta.env.PROD; |
| @@ -178,10 +203,7 @@ export function simplifyType(typeRef: string): string { | |||
|
|
|||
| // Clean assembly metadata from generic type arguments: | |||
| // System.IEquatable`1[[TypeName, Assembly, Version=..., ...]] → System.IEquatable`1[[TypeName]] | |||
| stripped = stripped.replace( | |||
| /\[\[([^\],]+),\s*[^\]]*\]\]/g, | |||
| '[[$1]]', | |||
| ); | |||
| stripped = stripped.replace(/\[\[([^\],]+),\s*[^\]]*\]\]/g, '[[$1]]'); | |||
There was a problem hiding this comment.
(nit) was it random to decide when to put a single statement on a line vs. when to put it all on one line?
These 2 changes appear to be just formatting changes, but in the opposite directions.
There was a problem hiding this comment.
That's a good callout. We do have a linter/formatting rule. We don't enforce though, as it's a bit heavy handed - while it might add a bit of extra review work, we don't want to block PRs.
Summary
This change addresses the API docs build regression by reducing repeated work during API page generation and trimming a couple of broad build inputs.
write-git-env.mjsdeterministic and avoid rewriting.env.localwhen values do not changeInclude.astrowith targeted docs collection lookupValidation
pnpm buildlocallygit diff --checkpnpm exec prettier --checkon changed filessrc/frontend/scripts/write-git-env.mjsNotes
Route fan-out reduction was intentionally left out of this PR.