Repository navigation
astro@7.4.0
Minor Changes
-
#17894
b7a1bd9Thanks @Princesseuh! - Adds a new--timingsflag toastro buildto help you find what slows down your buildsWhen a build takes longer than expected, it can be hard to tell whether the cause is an integration, a Markdown processor plugin, image processing, or even syntax highlighting. Add the
--timingsflag to your build command to print a summary once the build finishes:astro build --timings
This is helpful to decide what to optimize first, or to compare build times before and after a change to your project.
-
#17830
a937b0dThanks @florian-lefebvre! - Adds a new optionalgetFontProperties()callback to font providersFont providers can now expose the weights, styles, subsets and formats a font family actually has. Astro uses it when resolving your font configuration to warn about values a provider cannot serve, for example a weight a font family does not offer.
All built-in providers implement it. If you maintain a custom font provider, implementing this callback is optional for now but it will be required in Astro 8:
import type { FontProvider } from 'astro'; const provider: FontProvider = { name: 'my-provider', resolveFont: ({ familyName }) => { // ... }, getFontProperties: ({ familyName }) => ({ weights: ['400', '700'], styles: ['normal', 'italic'], subsets: ['latin'], formats: ['woff2'], }), };
-
#17830
a937b0dThanks @florian-lefebvre! - Adds afetch()function to the font providerinit()contextThis function requests a provider API, retrying transient failures and more. It lets providers that wrap a 3rd-party unifont provider pass the context to it directly:
import type { FontProvider } from 'astro'; import type { InitializedProvider } from 'unifont'; import { acmeProvider } from '@acme/unifont-provider'; export function acmeFontProvider(): FontProvider { const provider = acmeProvider(); let initializedProvider: InitializedProvider | undefined; return { name: provider._name, async init(context) { initializedProvider = await provider(context); }, // ... }; }
-
#18015
0b30239Thanks @florian-lefebvre! - Addsexperimental.redirectPage, letting you provide your ownsrc/pages/3xx.astroin place of the redirect page Astro generates in static builds.A static site has no server to send an HTTP
Locationheader, so Astro generates a small HTML page with a<meta http-equiv="refresh">tag for each redirect it builds:- Your
redirectsentries Astro.redirect()calls in prerendered pages- i18n redirects
That page's markup, wording, and refresh delay were fixed, so you could not brand or translate it.
To enable this feature, add the experimental flag to your Astro config:
// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { redirectPage: true, }, });
Then create
src/pages/3xx.astro. Astro renders it once per redirect, passing that redirect's details as props:--- // src/pages/3xx.astro import type { RedirectPageProps as Props } from 'astro'; const { from, to, status, delay } = Astro.props; --- <html lang="en"> <head> <meta http-equiv="refresh" content={`${delay};url=${to}`} /> <meta name="robots" content="noindex" /> <title>Redirecting…</title> </head> <body> <p>This page has moved. <a href={to}>Continue to {to}</a>.</p> </body> </html>
Your page must render a
<meta http-equiv="refresh">tag pointing atto, because in a static build that tag is the redirect. Astro logs a warning during the build if it is missing.See the experimental redirect page documentation for more information.
- Your
-
#18265
910ee69Thanks @astro-factory! - Adds anotFound()handler toastro/fetchandastro/honothat renders the custom 404 page when no route matches, including a prerendered404.astroAdd it before
pages()in a custom worker or server entrypoint that does not run insideApp.render, such as a Hono app used directly as a Cloudflare worker. Without it,pages()andmiddleware()return an empty 404 with an internalX-Astro-Errorheader for unmatched routes.astro()already includes this handling.import { Hono } from 'hono'; import { notFound, pages } from 'astro/hono'; import { cf } from '@astrojs/cloudflare/hono'; const app = new Hono(); app.use(cf()); app.use(notFound()); app.use(pages()); export default app;
-
#18177
7d814e5Thanks @Princesseuh! - Adds support for separatebuildandruntimeimage servicesimage.servicenow also accepts abuildand aruntimeservice. Thebuildservice optimizes images on prerendered pages when you build your site, and is also used during development. Theruntimeservice handles images on on-demand rendered pages and the image endpoint of your deployed site.The following example uses Sharp to optimize images on prerendered pages, and an image CDN for on-demand rendered pages:
// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ image: { service: { build: { entrypoint: 'astro/assets/services/sharp' }, runtime: { entrypoint: 'my-image-cdn-service' }, }, }, });
Changes for integration authors
config.image.servicekeeps the shape the user configured it with. When a project setsbuildandruntimeservices,config.image.service.entrypointandconfig.image.service.configareundefined.If your integration reads
image.service, check for theruntimeproperty to get the service you need:'astro:config:done': ({ config }) => { const { service } = config.image; const runtimeService = 'runtime' in service ? service.runtime : service; if (runtimeService.entrypoint === 'astro/assets/services/sharp') { // ... } },
Setting
image.servicewithupdateConfig()replaces the existing service instead of merging with it when the two use different shapes. For example, setting a single service in a project that usesbuildandruntimeservices replaces both. -
#18277
2715958Thanks @florian-lefebvre! - Increases the minimum Node.js version to 22.22.0The minimum supported Node.js version is now 22.22.0, the latest Node.js 22 release supported by StackBlitz. This change is in line with Astro's Node.js support policy.
-
#18313
71e2b24Thanks @matthewp! - Allows integrations to control where Astro writes client, server, and prerender build output.Custom prerenderers can access the final output locations through the new
outputDirectoriescontext:setPrerenderer((defaultPrerenderer, { outputDirectories }) => { const { client, server, prerender } = outputDirectories return createPrerenderer({ defaultPrerenderer, client, server, prerender, }) })
-
#18177
7d814e5Thanks @Princesseuh! - Lets custom prerenderers report the images used on prerendered pagesAstro now generates images on prerendered pages from the image information that a prerenderer's
getStaticPaths()andrender()return. If your prerenderer wraps Astro's default one, pass this information through:setPrerenderer((defaultPrerenderer) => ({ name: 'my-prerenderer', async setup() { await defaultPrerenderer.setup?.(); }, async getStaticPaths() { const result = await defaultPrerenderer.getStaticPaths(); const { paths, metadata } = Array.isArray(result) ? { paths: result } : result; return { paths: paths.filter(({ pathname }) => !pathname.startsWith('/drafts')), metadata }; }, render(request, options) { return defaultPrerenderer.render(request, options); }, async teardown() { await defaultPrerenderer.teardown?.(); }, }));
Returning a plain array from
getStaticPaths()or a plainResponsefromrender()still works, but is deprecated: images used on those pages are not generated. -
#17932
b905ff1Thanks @Princesseuh! - Adds support for experimental parallel prerenderingThis experimental feature makes
astro buildrender your static pages in parallel, using multiple CPU cores at once instead of one. On sites with many pages, this can significantly reduce build times, at the cost of higher memory usage.To enable this feature, add the experimental flag in your Astro config:
// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { parallelPrerender: true, }, });
By default, Astro uses all available CPU cores but one. Each additional worker increases the memory used by your build. If your build runs out of memory, or does not get faster, set
workersto a lower number:// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { parallelPrerender: { workers: 4, }, }, });
Each worker renders as many pages at once as your
build.concurrencysetting allows.This feature has no effect when your adapter provides its own way of prerendering pages. Among official adapters, this only applies to
@astrojs/cloudflare. Astro logs a warning during the build when the flag is ignored.For more information on enabling and using this feature in your project, see the experimental parallel prerendering docs.
Patch Changes
-
#18313
71e2b24Thanks @matthewp! - Fixes deployment integrations being unable to use Vite manifests when preparing build output -
#18270
0c3bf11Thanks @ArmandPhilippot! - Fixes the JSDoc for CSP utilities to point to the render context reference in docs. -
#18368
1f04637Thanks @43081j! - Replaces internal use offind-procwithtinyps. -
#18355
59b9cc0Thanks @matthewp! - Fixes prerender errors being silently swallowed when using a customsrc/fetch.tswith an adapter that prerenders in its own runtime, such as@astrojs/cloudflare. Previously, a page that threw during prerendering was written as an empty HTML file and the build succeeded. The build now fails with the underlying error. -
#18177
7d814e5Thanks @Princesseuh! - Fixes original images being kept despite onlywidthorheightbeing read. -
#18353
af54bfaThanks @astro-factory! - Fixesglob()loader swallowing rendering errors during content sync, which allowedastro buildto exit successfully (code 0) even when a remark/rehype plugin threw an error -
#18271
23e8e28Thanks @ArmandPhilippot! - Fixes thesynccommand description inastro help, which only mentioned content collections. -
Updated dependencies [
b7a1bd9,2715958]:- @astrojs/internal-helpers@0.13.0
- @astrojs/markdown-satteri@0.4.4
- @astrojs/telemetry@3.4.0