Skip to content

perf: serve header logo from hashed, CDN-cached static assets - #1979

Draft
marcleblanc2 wants to merge 1 commit into
mainfrom
marc/perf/inline-logo
Draft

marcleblanc2 wants to merge 1 commit into
mainfrom
marc/perf/inline-logo

Conversation

@marcleblanc2

@marcleblanc2 marcleblanc2 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Problem

The header logo is two <img> tags (light and dark variants) served from public/. Vercel serves public/ files with Cache-Control: public, max-age=0, so Cloudflare marks them cf-cache-status: BYPASS and every page load pays two origin round-trips (~155 ms each in the HAR of /docs/batch-changes/delete-a-batch-change).

Before After
URL /docs/logo-theme-{light,dark}.svg /_next/static/media/logo-theme-{light,dark}.<hash>.svg
Cache-Control public, max-age=0 public, max-age=31536000, immutable
Cloudflare BYPASS HIT (same path class as fonts and JS chunks)

Fix

Move the two SVGs from public/ to src/images/ and import them in Logo.tsx via next/image. Webpack emits them into /_next/static/media/ with a content hash and the one-year immutable header, the same as every other static asset. The component keeps the same two-<img> theme switch (dark:hidden / dark:block) and priority, so there is no visual or LCP change.

The OG image route (src/app/api/og/[...path]/route.tsx) read the dark logo from public/ at request time; it now reads from src/images/.

Verification

  • tsc --noEmit, pnpm lint, pnpm build clean.
  • next start renders src="/_next/static/media/logo-theme-dark.8264a8f4.svg" and logo-theme-light.d258bd04.svg, both image/svg+xml with Cache-Control: public, max-age=31536000, immutable.
  • /api/og/... still returns 200 image/png.
  • Header screenshots of prod vs this branch are byte-identical PNGs for both themes.

Before and after header, light and dark

Notes

  • Earlier revision of this PR inlined the SVG into the component instead. That removed the requests entirely but dropped the CDN, so this version imports the files instead and lets Cloudflare cache them.
  • Any other public/ asset referenced from the layout has the same problem; the same import pattern fixes it.

@vercel

vercel Bot commented Sep 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
sourcegraph-docs Ready Ready Preview Sep 17, 2026 10:22am UTC

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

This comment has been minimized.

Import the two logo SVGs instead of serving them from public/, so
they ship from /_next/static/media/ with a content hash and a
one-year immutable Cache-Control header, and Cloudflare caches them
like the rest of the static bundle. public/ files are served with
max-age=0 and BYPASS the Cloudflare cache, costing two origin
round-trips on every page load.

The OG image route now reads the dark logo from src/images/.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0ac9d-704f-73fe-8211-1b3e5840969f
Co-authored-by: Amp <amp@ampcode.com>
@marcleblanc2 marcleblanc2 changed the title perf: inline the header logo perf: serve header logo from hashed, CDN-cached static assets Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant