Release Notes
Minor Changes
#17302
5f4dc03Thanks @astrobot-houston! - Adds a newdeferRenderoption to theglob()content loaderWhen set to
true, renderable entries (such as Markdown) are not rendered during content sync. Instead, rendering is deferred until the entry is actually rendered in a page, using the same on-demand path that.mdxfiles already use.This reduces memory usage during
astro buildfor large collections whose rendered output is much larger than the source — for example, Markdown that uses heavy rehype plugins likerehype-katex. Such builds could previously run out of memory while storing the eagerly-rendered HTML for every entry.// src/content.config.ts import { defineCollection } from 'astro:content'; import { glob } from 'astro/loaders'; const docs = defineCollection({ loader: glob({ pattern: '**/*.md', base: 'src/content/docs', deferRender: true }), });By default
deferRenderisfalse, preserving the existing behavior of rendering entries eagerly during sync so their rendered HTML can be cached across builds.#17296
30698a2Thanks @ematipico! - Adds a new experimentalcollectionStorageoption for controlling how the content layer persists its data storeBy default, Astro serializes the entire content layer data store to a single file (
.astro/data-store.json). For very large content collections, this file can grow large enough to hit platform file-size limits.Set
experimental.collectionStorage: 'chunked'to instead split the data store across many smaller, content-addressed files inside a.astro/data-store/directory, described by a manifest:// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { collectionStorage: 'chunked', }, });Because each part file is named by a hash of its contents, unchanged parts keep the same name across builds and are not rewritten, and identical parts are deduplicated. The default value is
'single-file', which preserves the current behavior.#17214
44c4989Thanks @ematipico! - Adds support for the more specific CSP directivesscript-src-elem,script-src-attr,style-src-elem, andstyle-src-attrthrough a newkindoption.Previously,
CSPwas only scoped to genericscript-src/style-srcdirectives. Now each source or hash can be scoped to a narrower directive — for example, to allow inlinestyleattributes (such as those fromdefine:varsor Shiki) without loosening the policy for your<style>and<link>elements.Scoping sources and hashes in your config
Each entry in
resourcesandhashescan be an object with akindproperty. Depending on whether you usescriptDirectiveorstyleDirective,"element"targetsscript-src-elemorstyle-src-elem,"attribute"targetsscript-src-attrorstyle-src-attr, and"default"(the same as a bare string or hash) targetsscript-srcorstyle-src.// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ security: { csp: { scriptDirective: { resources: [{ resource: 'https://cdn.example.com', kind: 'element' }], }, styleDirective: { resources: [{ resource: "'unsafe-inline'", kind: 'attribute' }], }, }, }, });Scoping at runtime
The same
kindoption is available on the runtime CSP API, where the existing methods now also accept an object:ctx.csp.insertScriptResource({ resource: 'https://cdn.example.com', kind: 'element' }); ctx.csp.insertStyleResource({ resource: "'unsafe-inline'", kind: 'attribute' });#17258
84814d4Thanks @astrobot-houston! - Adds a newformat()option to thepaginateutility. Theformat()option is a function that accepts the current URL of the page, and returns a new URL.For example, when your host only supports URLs using the
.htmlextension, you can useformat()to add it to the generated URLs:--- export async function getStaticPaths({ paginate }) { // Load your data with fetch(), getCollection(), etc. const response = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=150`); const result = await response.json(); const allPokemon = result.results; // Return a paginated collection of paths for all items return paginate(allPokemon, { pageSize: 10, format: (url) => `${url}.html`, }); } const { page } = Astro.props; ---#17331
7db6420Thanks @matthewp! - Adds a--ignore-lockflag toastro devfor starting a dev server without checking or writing the lock file, so it can run alongside an already-running dev server for the same project.The new instance is not tracked by
astro dev stop,astro dev status, orastro dev logs.--ignore-lockcannot be combined with--background(or an auto-detected AI agent environment, which runs dev servers in the background automatically) or--force, since those rely on the lock file.astro dev --ignore-lock#17389
16de021Thanks @florian-lefebvre! - Allows passing URL entrypoints when configuring the loggerMatching other APIs like session drivers or font providers, the logger entrypoint can now be a URL:
import { defineConfig } from 'astro/config'; export default defineConfig({ logger: { entrypoint: new URL('./logger.js', import.meta.url), }, });
Patch Changes
#17332
4407483Thanks @astrobot-houston! - Fixes the JSON logger crashing withprocess is not definedin non-Node runtimes like Cloudflare's workerd. The JSON logger now usesconsole.log/console.errorinstead ofprocess.stdout/process.stderr, matching the pattern already used by the console logger.#17391
186a1e7Thanks @florian-lefebvre! - Fixes a case where an integration could not update the logger withupdateConfig()#17394
d9f99e1Thanks @matthewp! - Fixes element-specific CSP directives to preserve the existing behavior of configured script and style resources#17374
b2d1b3eThanks @astrobot-houston! - Fixes dev server returning 404 for?urlimported assets when accessed via browser navigation#17390
ed71eafThanks @florian-lefebvre! - Removes an unused and undocumented generic from theAstroLoggerDestinationtype#17393
092da56Thanks @matthewp! - Hardens generated transition styles, development metadata, and server island URLs when embedding dynamic values