Fix prerendered redirect targets inflating SSR bundle in hybrid mode#17066
Merged
Conversation
Closes #17060 Supersedes #17061 Related: cb95536, 8d5f783 The getRoutesForEnvironment function unconditionally added every redirect's target route (via route.redirectRoute) to the environment's route set. In hybrid mode (output: 'static' + adapter), this pulled prerendered pages into the SSR bundle even though they should only exist in the prerender environment. The reporter saw their deployment grow from ~1.4MB to 68MB because 4 prerendered redirect targets dragged in all their static dependencies. The redirectRoute block was added in cb95536 ('fix: include redirectRoute in environment route filtering') within PR #15093 as a safety measure, with the assumption that redirect responses need the target's component at runtime. After tracing the full runtime path, this turns out to be wrong: 1. AstroHandler.render() (routing/handler.ts:127) short-circuits redirect routes before any component loading — renderRedirect() only uses route metadata (segments, pathname) to compute the Location header. 2. getModuleForRoute in AppPipeline does swap to the target's component for redirects, but this codepath is never reached at SSR runtime because of the short-circuit above. 3. The only place that needs the target's component is prerendering (StaticPaths calls getComponentByRoute to invoke getStaticPaths on dynamic targets), but prerendered redirects and their targets share the same prerender flag, so both are already included by the route.prerender === isPrerender check. 4. The redirectRoute property is a reference to an existing RouteData object that already appears in the routes array (it comes from routeMap.get(destination) in create-manifest.ts:545). The redirectRoute block was redundant for matching-environment targets and harmful for cross-environment targets. PR #17061 proposed adding route.redirectRoute.prerender === isPrerender, which is correct but still redundant — the target with matching prerender is already in the set from its own loop iteration. The simpler fix is to remove the redirectRoute block entirely.
🦋 Changeset detectedLatest commit: 62ced03 The changes in this PR will be included in the next version bump. This PR includes changesets to release 400 packages
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 |
commit: |
Contributor
Author
|
@spaceemotion can you try the preview release in this PR and tell me if it also fixes your problem? |
|
@matthewp seems to work as well! just installed the pkg preview build and the output folder is as slim as with the other patch (i removed the local patch and checked by |
Covers all four combinations of redirect/target prerender flags to verify that redirect targets are only included in the environment matching their own prerender flag.
ematipico
approved these changes
Jun 15, 2026
Merged
dadezzz
pushed a commit
to dadezzz/university_notes
that referenced
this pull request
Jun 19, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`6.4.6` → `6.4.7`](https://renovatebot.com/diffs/npm/astro/6.4.6/6.4.7) |  |  | --- ### Release Notes <details> <summary>withastro/astro (astro)</summary> ### [`v6.4.7`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#647) [Compare Source](https://github.com/withastro/astro/compare/astro@6.4.6...astro@6.4.7) ##### Patch Changes - [#​17035](withastro/astro#17035) [`197e50e`](withastro/astro@197e50e) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes `getRelativeLocaleUrl`, `getAbsoluteLocaleUrl`, and `getAbsoluteLocaleUrlList` to strip trailing slashes when `trailingSlash: 'never'` is configured - [#​16967](withastro/astro#16967) [`3719765`](withastro/astro@3719765) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes double URL-encoded paths returning 400 Bad Request on on-demand routes Previously, any URL containing a double-encoded character (like `%255B`, which is `[` encoded twice) was unconditionally rejected with a `400 Bad Request` before middleware or route handlers could run. This broke embedded tools like Sanity Studio whose client-side router legitimately produces double-encoded URLs. The fix replaces the rejection approach with iterative decoding — multi-level percent-encoding is now fully resolved to its canonical form before being passed to middleware and route matching. This preserves the security fix for CVE-2025-66202 (middleware authorization bypass via double encoding) because middleware now always sees the fully decoded path, making bypass impossible. For example, `/api/%2561dmin` is decoded to `/api/admin`, which middleware can correctly block. - [#​17066](withastro/astro#17066) [`2f4d92a`](withastro/astro@2f4d92a) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes prerendered redirect targets being incorrectly bundled into the SSR function in hybrid mode, causing massive bundle size inflation - [#​16882](withastro/astro#16882) [`621beb7`](withastro/astro@621beb7) Thanks [@​jettwayio](https://github.com/jettwayio)! - fix(render): honour compressHTML when joining head elements - [#​16892](withastro/astro#16892) [`8d753b0`](withastro/astro@8d753b0) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes custom elements in MDX having their children's `slot` attribute stripped by the JSX runtime When custom elements (tags with hyphens like `<my-element>`) are used in MDX files, the `slot` HTML attribute on their children is now correctly preserved. Previously, the shared JSX runtime would treat `slot` as an Astro slot assignment and remove it from the output, breaking Shadow DOM named slot distribution for web components. - [#​16957](withastro/astro#16957) [`544ee76`](withastro/astro@544ee76) Thanks [@​thelazylamaGit](https://github.com/thelazylamaGit)! - Fixes stale inline CSS in server-rendered HTML after CSS file edits during dev When editing a CSS file (`.css`, `.scss`, etc.) during development, the inline `<style>` tags in server-rendered HTML would retain old CSS content instead of updating. This caused a brief flash of old CSS (FOUC) on fresh page loads before Vite's client-side HMR corrected the styles. The fix ensures that Astro's per-route dev CSS virtual modules are invalidated in both the SSR module graph and the module runner's evaluation cache when a style file changes, so the next page render picks up the fresh CSS. - [#​17044](withastro/astro#17044) [`2220d22`](withastro/astro@2220d22) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes CSS from `client:only` islands leaking to unrelated pages when Rollup bundles non-CSS-importing modules into the same chunk as CSS-importing modules - [#​17040](withastro/astro#17040) [`7c4763d`](withastro/astro@7c4763d) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes HMR not triggering for files inside the `src/middleware/` directory during dev - [#​16672](withastro/astro#16672) [`52fc862`](withastro/astro@52fc862) Thanks [@​martinheidegger](https://github.com/martinheidegger)! - Fixes support for numeric IDs in YAML frontmatter when using content collection references - [#​16762](withastro/astro#16762) [`9de80ae`](withastro/astro@9de80ae) Thanks [@​alexanderdombroski](https://github.com/alexanderdombroski)! - Adds a JSON schema to the Wrangler configuration file generated when running `astro add cloudflare` - [#​17046](withastro/astro#17046) [`ef771ec`](withastro/astro@ef771ec) Thanks [@​ematipico](https://github.com/ematipico)! - Improves the diagnostics emitted when Astro parses incorrect `.astro` files. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
1 task
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.
Changes
redirectRouteinclusion fromgetRoutesForEnvironmentinpackages/astro/src/vite-plugin-pages/pages.ts. In hybrid mode (output: 'static'+ adapter), this was pulling prerendered pages into the SSR bundle when they were targets of config-level redirects, inflating the bundle by orders of magnitude (reporter saw 68MB vs ~1.4MB).route.redirectRoute.prerender === isPrerenderguard, which is correct but redundant — redirect targets already appear in the routes list with their ownprerenderflag and are included by the existingroute.prerender === isPrerendercheck during their own iteration. Removing the block entirely is the right fix because:renderRedirectusessegments/pathnamefor theLocationheader). No component is loaded —AstroHandler.render()short-circuits beforegetModuleForRouteis ever called.getStaticPathson dynamic targets), but prerendered redirects and their targets share the sameprerenderflag, so both are already in the prerender environment's route set.Closes #17060
Supersedes #17061
Testing
packages/astro/test/units/redirects/environment-filtering.test.tswith 4 test cases covering all combinations of redirect/target prerender flags: SSR redirect to prerendered target (must exclude target from SSR set), prerendered redirect to prerendered target (both included), SSR redirect to SSR target (both included), prerendered redirect to SSR target (must exclude target from prerender set).Docs