Minor Changes
-
#11657
a23c69d
Thanks @bluwy! - Deprecates the option for route-generating files to export a dynamic value forprerender
. Only static values are now supported (e.g.export const prerender = true
or= false
). This allows for better treeshaking and bundling configuration in the future.Adds a new
"astro:route:setup"
hook to the Integrations API to allow you to dynamically set options for a route at build or request time through an integration, such as enabling on-demand server rendering.To migrate from a dynamic export to the new hook, update or remove any dynamic
prerender
exports from individual routing files:// src/pages/blog/[slug].astro - export const prerender = import.meta.env.PRERENDER
Instead, create an integration with the
"astro:route:setup"
hook and update the route'sprerender
option:// astro.config.mjs import { defineConfig } from 'astro/config'; import { loadEnv } from 'vite'; export default defineConfig({ integrations: [setPrerender()], }); function setPrerender() { const { PRERENDER } = loadEnv(process.env.NODE_ENV, process.cwd(), ''); return { name: 'set-prerender', hooks: { 'astro:route:setup': ({ route }) => { if (route.component.endsWith('/blog/[slug].astro')) { route.prerender = PRERENDER; } }, }, }; }
-
#11360
a79a8b0
Thanks @ascorbic! - Adds a newinjectTypes()
utility to the Integration API and refactors how type generation worksUse
injectTypes()
in theastro:config:done
hook to inject types into your user's project by adding a new a*.d.ts
file.The
filename
property will be used to generate a file at/.astro/integrations/<normalized_integration_name>/<normalized_filename>.d.ts
and must end with".d.ts"
.The
content
property will create the body of the file, and must be valid TypeScript.Additionally,
injectTypes()
returns a URL to the normalized path so you can overwrite its content later on, or manipulate it in any way you want.// my-integration/index.js export default { name: 'my-integration', 'astro:config:done': ({ injectTypes }) => { injectTypes({ filename: 'types.d.ts', content: "declare module 'virtual:my-integration' {}", }); }, };
Codegen has been refactored. Although
src/env.d.ts
will continue to work as is, we recommend you update it:- /// <reference types="astro/client" /> + /// <reference path="../.astro/types.d.ts" /> - /// <reference path="../.astro/env.d.ts" /> - /// <reference path="../.astro/actions.d.ts" />
-
#11605
d3d99fb
Thanks @jcayzac! - Adds a new propertymeta
to Astro's built-in<Code />
component.This allows you to provide a value for Shiki's
meta
attribute to pass options to transformers.The following example passes an option to highlight lines 1 and 3 to Shiki's
tranformerMetaHighlight
:--- // src/components/Card.astro import { Code } from 'astro:components'; import { transformerMetaHighlight } from '@shikijs/transformers'; --- <Code code={code} lang="js" transformers={[transformerMetaHighlight()]} meta="{1,3}" />
-
#11360
a79a8b0
Thanks @ascorbic! - Adds support for Intellisense features (e.g. code completion, quick hints) for your content collection entries in compatible editors under theexperimental.contentIntellisense
flag.import { defineConfig } from 'astro'; export default defineConfig({ experimental: { contentIntellisense: true, }, });
When enabled, this feature will generate and add JSON schemas to the
.astro
directory in your project. These files can be used by the Astro language server to provide Intellisense inside content files (.md
,.mdx
,.mdoc
).Note that at this time, this also require enabling the
astro.content-intellisense
option in your editor, or passing thecontentIntellisense: true
initialization parameter to the Astro language server for editors using it directly.See the experimental content Intellisense docs for more information updates as this feature develops.
-
#11360
a79a8b0
Thanks @ascorbic! - Adds experimental support for the Content Layer API.The new Content Layer API builds upon content collections, taking them beyond local files in
src/content/
and allowing you to fetch content from anywhere, including remote APIs. These new collections work alongside your existing content collections, and you can migrate them to the new API at your own pace. There are significant improvements to performance with large collections of local files.Getting started
To try out the new Content Layer API, enable it in your Astro config:
import { defineConfig } from 'astro'; export default defineConfig({ experimental: { contentLayer: true, }, });
You can then create collections in your
src/content/config.ts
using the Content Layer API.Loading your content
The core of the new Content Layer API is the loader, a function that fetches content from a source and caches it in a local data store. Astro 4.14 ships with built-in
glob()
andfile()
loaders to handle your local Markdown, MDX, Markdoc, and JSON files:// src/content/config.ts import { defineCollection, z } from 'astro:content'; import { glob } from 'astro/loaders'; const blog = defineCollection({ // The ID is a slug generated from the path of the file relative to `base` loader: glob({ pattern: '**/*.md', base: './src/data/blog' }), schema: z.object({ title: z.string(), description: z.string(), publishDate: z.coerce.date(), }), }); export const collections = { blog };
You can then query using the existing content collections functions, and enjoy a simplified
render()
function to display your content:--- import { getEntry, render } from 'astro:content'; const post = await getEntry('blog', Astro.params.slug); const { Content } = await render(entry); --- <Content />
Creating a loader
You're not restricted to the built-in loaders – we hope you'll try building your own. You can fetch content from anywhere and return an array of entries:
// src/content/config.ts const countries = defineCollection({ loader: async () => { const response = await fetch('https://restcountries.com/v3.1/all'); const data = await response.json(); // Must return an array of entries with an id property, // or an object with IDs as keys and entries as values return data.map((country) => ({ id: country.cca3, ...country, })); }, // optionally add a schema to validate the data and make it type-safe for users // schema: z.object... }); export const collections = { countries };
For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading, and gives full access to the data store. It also allows a loader to define its own schema, including generating it dynamically based on the source API. See the the Content Layer API RFC for more details.
Sharing your loaders
Loaders are better when they're shared. You can create a package that exports a loader and publish it to npm, and then anyone can use it on their site. We're excited to see what the community comes up with! To get started, take a look at some examples. Here's how to load content using an RSS/Atom feed loader:
// src/content/config.ts import { defineCollection } from 'astro:content'; import { feedLoader } from '@ascorbic/feed-loader'; const podcasts = defineCollection({ loader: feedLoader({ url: 'https://feeds.99percentinvisible.org/99percentinvisible', }), }); export const collections = { podcasts };
Learn more
To find out more about using the Content Layer API, check out the Content Layer RFC and share your feedback.
Patch Changes
-
#11716
f4057c1
Thanks @florian-lefebvre! - Fixes content types sync in dev -
#11645
849e4c6
Thanks @bluwy! - Refactors internally to usenode:util
parseArgs
instead ofyargs-parser
-
#11712
791d809
Thanks @matthewp! - Fix mixed use of base + trailingSlash in Server Islands -
#11709
3d8ae76
Thanks @matthewp! - Fix adapter causing Netlify to break