feat(@angular/build): add prerenderFormat option to prerender routes as <route>.html - #34180
Draft
JohannesHoppe wants to merge 1 commit into
Draft
JohannesHoppe wants to merge 1 commit into
JohannesHoppe wants to merge 1 commit into
Conversation
JohannesHoppe
force-pushed
the
feat/prerender-format
branch
from
September 25, 2026 18:10
5a28f55 to
e5d9701
Compare
…s as `<route>.html` Prerendered routes are written to `<route>/index.html`. Static hosts serve such a file under `/<route>/`, so a request to `/<route>` is first redirected to the URL with a trailing slash, which the Angular router then removes again. The new `prerenderFormat` option of the application builder accepts `directory` (default, unchanged behavior) and `file`, like the `build.format` option of Astro. With `file`, routes are written to `<route>.html`, which avoids the redirect on hosts that serve `<route>.html` for `/<route>`. The root route of the application and of each locale is still written to `index.html`. Static redirect pages follow the same layout. A route whose last segment is `index` is reported as a build error with `file`. `file` is only supported when the build does not produce a server (for example with `outputMode: "static"`), because the `@angular/ssr` runtime looks up prerendered pages as `<route>/index.html`. The dev server resets the option when it switches prerendering to on-demand SSR. Closes angular#29173
JohannesHoppe
force-pushed
the
feat/prerender-format
branch
from
September 25, 2026 19:25
e5d9701 to
0da3613
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
Please check to confirm your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Prerendering always writes a route to
<route>/index.html. On static hosts, this forces a choice between clean URLs and no redirects. You can't have both:/<route>. Every direct request (search engines, bookmarks, shared links) is first redirected (301/308) to/<route>/, and the Angular router then removes the trailing slash again./<route>/, and the app needsTrailingSlashPathLocationStrategyto keep the slash in the address bar.Issue Number: #29173
What is the new behavior?
A new application builder option
prerenderFormatmakes both possible: clean URLs without a trailing slash, served directly with a status code 200."directory"(default):/foo/baris written tofoo/bar/index.html, unchanged."file":/foo/baris written tofoo/bar.html, so hosts that serve<route>.htmlfor/<route>respond to/foo/barwithout a redirect.Mirrors Astro's
build.format('directory' | 'file'); Next.js, SvelteKit and Hugo offer the same choice viatrailingSlash/uglyURLs.index.html, so/and/<locale>/keep being served by the host's directory index."file"requires a build without a server. The@angular/ssrruntime looks up prerendered pages as<route>/index.html(AngularServerApp.buildServerAssetPathFromRequest,CommonEngine.retrieveSSGPage), and with a server there is no redirect to avoid, since the generatedserver.tsserves static files withredirect: false.index(for example/indexor/Index) is reported as an error with"file", because its file would beindex.htmlof the parent path.ng servereports the same error asng build.prerender, becauseprerenderis not considered whenoutputModeis set.As suggested by @SanderElias in the issue, the option description states that not all hosting services support this. Happy to rename the option if you prefer a different name.
Does this PR introduce a breaking change?
Other information
As a stopgap, I built a builder (
@angular-schule/prerender-format) that wraps@angular/build:application. It only works by replacing the internalprerenderPages()export of@angular/buildat runtime to rename the output files, which is fragile and can break with any internal refactoring. A built-in option is the clean solution.The option description in
schema.jsonfeeds theng buildreference on angular.dev. If this lands, I'm happy to follow up with a short section in the SSR guide ("Generate a fully static application") in angular/angular.