Major Changes
-
#11864
ee38b3a
Thanks @ematipico! - ### [changed]:entryPoint
type inside the hookastro:build:ssr
In Astro v4.x, theentryPoint
type wasRouteData
.Astro v5.0 the
entryPoint
type isIntegrationRouteData
, which contains a subset of theRouteData
type. The fieldsisIndex
andfallbackRoutes
were removed.What should I do?
Update your adapter to change the type of
entryPoint
fromRouteData
toIntegrationRouteData
.-import type {RouteData} from 'astro'; +import type {IntegrationRouteData} from "astro" -function useRoute(route: RouteData) { +function useRoute(route: IntegrationRouteData) { }
-
#11908
518433e
Thanks @Princesseuh! - Theimage.endpoint
config now allow customizing the route of the image endpoint in addition to the entrypoint. This can be useful in niche situations where the default route/_image
conflicts with an existing route or your local server setup.import { defineConfig } from 'astro/config'; defineConfig({ image: { endpoint: { route: '/image', entrypoint: './src/image_endpoint.ts', }, }, });
-
#11806
f7f2338
Thanks @Princesseuh! - Removes theassets
property onsupportedAstroFeatures
for adapters, as it did not reflect reality properly in many cases.Now, relating to assets, only a single
sharpImageService
property is available, determining if the adapter is compatible with the built-in sharp image service. -
#11864
ee38b3a
Thanks @ematipico! - ### [changed]:routes
type inside the hookastro:build:done
In Astro v4.x, theroutes
type wasRouteData
.Astro v5.0 the
routes
type isIntegrationRouteData
, which contains a subset of theRouteData
type. The fieldsisIndex
andfallbackRoutes
were removed.What should I do?
Update your adapter to change the type of
routes
fromRouteData
toIntegrationRouteData
.-import type {RouteData} from 'astro'; +import type {IntegrationRouteData} from "astro" -function useRoute(route: RouteData) { +function useRoute(route: IntegrationRouteData) { }
-
#11864
ee38b3a
Thanks @ematipico! - ### [changed]:RouteData.distURL
is now an array
In Astro v4.x,RouteData.distURL
wasundefined
or aURL
Astro v5.0,
RouteData.distURL
isundefined
or an array ofURL
. This was a bug, because a route can generate multiple files on disk, especially when using dynamic routes such as[slug]
or[...slug]
.What should I do?
Update your code to handle
RouteData.distURL
as an array.if (route.distURL) { - if (route.distURL.endsWith('index.html')) { - // do something - } + for (const url of route.distURL) { + if (url.endsWith('index.html')) { + // do something + } + } }
Minor Changes
-
#11806
f7f2338
Thanks @Princesseuh! - The value of the different properties onsupportedAstroFeatures
for adapters can now be objects, with asupport
andmessage
properties. The content of themessage
property will be shown in the Astro CLI when the adapter is not compatible with the feature, allowing one to give a better informational message to the user.This is notably useful with the new
limited
value, to explain to the user why support is limited. -
#11955
d813262
Thanks @matthewp! - Server Islands introduced behind an experimental flag in v4.12.0 is no longer experimental and is available for general use.Server islands are Astro's solution for highly cacheable pages of mixed static and dynamic content. They allow you to specify components that should run on the server, allowing the rest of the page to be more aggressively cached, or even generated statically.
Turn any
.astro
component into a server island by adding theserver:defer
directive and optionally, fallback placeholder content. It will be rendered dynamically at runtime outside the context of the rest of the page, allowing you to add longer cache headers for the pages, or even prerender them.--- import Avatar from '../components/Avatar.astro'; import GenericUser from '../components/GenericUser.astro'; --- <header> <h1>Page Title</h1> <div class="header-right"> <Avatar server:defer> <GenericUser slot="fallback" /> </Avatar> </div> </header>
If you were previously using this feature, please remove the experimental flag from your Astro config:
import { defineConfig } from 'astro/config'; export default defineConfig({ experimental { - serverIslands: true, }, });
If you have been waiting for stabilization before using server islands, you can now do so.
Please see the server island documentation for more about this feature.
-
#11806
f7f2338
Thanks @Princesseuh! - Adds a newlimited
value for the different properties ofsupportedAstroFeatures
for adapters, which indicates that the adapter is compatible with the feature, but with some limitations. This is useful for adapters that support a feature, but not in all cases or with all options. -
#11925
74722cb
Thanks @florian-lefebvre! - Updatesastro/config
import to referenceastro/client
typesWhen importing
astro/config
, types fromastro/client
will be made automatically available to your project. If your projecttsconfig.json
changes how references behave, you'll still have access to these types after runningastro sync
.
Patch Changes
-
#11974
60211de
Thanks @ascorbic! - Exports theRenderResult
type -
#11939
7b09c62
Thanks @bholmesdev! - Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation.This example accepts either a
create
orupdate
form submission, and uses thetype
field to determine which object to validate against.import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { changeUser: defineAction({ accept: 'form', input: z.discriminatedUnion('type', [ z.object({ type: z.literal('create'), name: z.string(), email: z.string().email(), }), z.object({ type: z.literal('update'), id: z.number(), name: z.string(), email: z.string().email(), }), ]), async handler(input) { if (input.type === 'create') { // input is { type: 'create', name: string, email: string } } else { // input is { type: 'update', id: number, name: string, email: string } } }, }), };
The corresponding
create
andupdate
forms may look like this:--- import { actions } from 'astro:actions'; --- <!--Create--> <form action={actions.changeUser} method="POST"> <input type="hidden" name="type" value="create" /> <input type="text" name="name" required /> <input type="email" name="email" required /> <button type="submit">Create User</button> </form> <!--Update--> <form action={actions.changeUser} method="POST"> <input type="hidden" name="type" value="update" /> <input type="hidden" name="id" value="user-123" /> <input type="text" name="name" required /> <input type="email" name="email" required /> <button type="submit">Update User</button> </form>