feat(web): allow the static export's assets to be served from a prefix - #1014
feat(web): allow the static export's assets to be served from a prefix#1014jiashuoz wants to merge 1 commit into
Conversation
Adds an optional NEXT_ASSET_PREFIX passthrough to next.config.ts. Unset everywhere by default, so the published image, the dev server and self-hosted builds are unchanged. It exists for deployments that build the static export more than once at different cadences -- e.g. serving the marketing pages from one build and the dashboard from another. Both would otherwise claim /_next/*, and only one of them can own that path. A self-hoster serving assets from a CDN subpath can use it the same way. Verified against a real build (Next 16, output: "export"): - with NEXT_ASSET_PREFIX=/_marketing, every script/style/font reference becomes /_marketing/_next/static/..., with no bare /_next left; - with it unset, the export is byte-identical to a build from the unmodified config across all 380 files, modulo Next's random per-build ID directory and the <lastmod> timestamps sitemap.ts stamps at build time. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GB8rYQbBBqow6ZmZ7JdyqD
Parked with the hosted-side work (tokencanopy/e2a-ops #375, #376 are drafts)This PR is the safest of the set and is independently verified: with Two things to fold in before merging:
Also worth adding |
One optional config line:
assetPrefix: process.env.NEXT_ASSET_PREFIX || undefined.Why
A deployment that builds this static export more than once, at different cadences, hits a collision: both builds emit
/_next/*and only one of them can own that path. Concretely — serving the marketing pages (which change with copy) separately from the dashboard (which must match the deployed server version).assetPrefixgives one of the builds its own asset namespace.It's also the standard way to serve a static export's assets from a CDN subpath, so it's useful to self-hosters independently of that.
Why it's safe
Unset everywhere by default. Verified against real builds (Next 16,
output: "export"):NEXT_ASSET_PREFIX=/_marketing: every script, stylesheet and font reference becomes/_marketing/_next/static/..., with no bare/_nextleft in the emitted HTML._next/static/<id>/_buildManifest.js) and the<lastmod>timestampssitemap.tsstamps at build time.|| undefinedrather than|| ""is deliberate: Next maps an emptyassetPrefixontobasePath, which is a different behaviour from "no prefix configured".No test here, on purpose
next.config.tsusesimport.meta, so jest (CJS) can't load it, and reshaping the config to make it unit-testable would be a worse trade than the guard it buys. The consumer asserts it end-to-end instead: the hosted build's bundle test checks the emitted HTML actually references/_marketing/_next/, which fails loudly if this option is ever removed.🤖 Generated with Claude Code
https://claude.ai/code/session_01GB8rYQbBBqow6ZmZ7JdyqD