We just released Astro 2.1, featuring:
- Built-in Image Support: (experimental) Automatic image optimization is landing in Astro core.
- Markdoc Integration: (experimental) A new content format from Stripe, optimized for large projects.
astro check --watch
: Use this flag to type check your.astro
files during development.- Inferred types for dynamic routes: Get the params and props without defining the types twice.
Astro 2.1 is available on npm today. Run npm i astro@latest
to upgrade an existing project or run npm create astro
in the terminal to start something new.
Built-in Image Support
Astro 2.1 brings experimental support for built-in image optimization to Astro. To enable it in your project, run Astro with the --experimental-assets
flag or set the experimental.assets
boolean flag in your Astro config file.
If you’re already familiar with our original @astrojs/image
integration, Astro’s new built-in <Image>
component should feel familiar but with some notable improvements. You can now adjust the size of the image using the width
and height
props without changing its aspect ratio and control the level of image optimization using the new quality
prop.
---import { Image } from "astro:assets"import penguin from "~/assets/penguin.png"---
<Image src={penguin} quality="high" alt="a high-quality penguin" />
The resulting image will be automatically optimized for you in a modern web format, for maximum performance with minimum Cumulative Layout Shift (CLS).
Additionally the built-in image support can be swapped out for another provider, allowing you to connect this to an production image CDN like Cloudinary or a host like Vercel to leverage their image optimization services instead.
Astro 2.1 also answers one of our most requested features coming out of the original 2.0 launch: image handling inside of content collections. A new image()
schema helper is now available from the Content Collections API that lets you define images in your frontmatter schema.
import { image, defineCollection, z } from "astro:content"
const blogCollection = defineCollection({ schema: z.object({ title: z.string(), cover: image(), }),})
export const collections = { blog: blogCollection,}
If the image that you reference in your frontmatter doesn’t exist, Astro will let you know. You can refine the schema even further to check for things like image dimensions and file extension:
cover: image().refine((img) => img.width === 800 && img.height === 600, { message: "Cover needs to be 800x600 pixels!",})
To try it for yourself, check out the migration instructions in our new Assets Guide. We’ll continue to revise and improve support for images until the feature is stable and the flag dropped in a future major release. You can contribute your feedback by commenting on the Image RFC.
Markdoc integration
A new experimental Markdoc integration has also been published alongside Astro 2.1. You can add @astrojs/markdoc
to your project today by running npx astro add markdoc
in your project directory.
Markdoc is a promising new content format developed by Stripe when they needed something that could match their scale. While we still love MDX for Astro, it’s not uncommon for our users to see a noticable slowdown when processing a large number of MDX files.
As part of our own investigation, we built a performance benchmark to compare Markdoc build performance inside of Astro against our existing content formats: Markdown and MDX. These tests show exciting improvements, with up to 3x faster builds over MDX rendering static content and islands of interactivity.
Once the @astrojs/markdoc
integration has been added to your project, Markdoc becomes available exclusively inside of Content Collections using the .mdoc
file extension. You can mix Markdoc files alongside your existing Markdown and MDX files for a smooth, gradual migration process.
Support for MDX is not going away. We are experimenting with both formats as we feel out what the future of content looks like in Astro. We’d love your feedback as we try to find the right balance between flexible syntax and scaling to larger sites. Especially if this is your first time trying Markdoc, give us your thoughts in the ongoing Markdoc RFC.
astro check —watch
astro check
is a built-in Astro CLI command that runs TypeScript type checking on your project .astro
files. It is often used to catch bugs and type errors in CI before merging changes or deploying your site.
We heard from some users that they wanted this same feature for development, similar to tsc --watch
in TypeScript. For some, getting errors in your editor is easy to miss, and it can be easy to forget to run astro check
manually before pushing a change.
In Astro 2.1, a new --watch
flag has been added to the astro check
command. This will spawn a long-running process that listens for file changes and reruns diagnostics on changed files. You can run this in parallel with your dev server with by adding a script to your package.json
:
{ "scripts": { "dev": "astro check --watch & astro dev" }}
Inferred types for dynamic routes
The getStaticPaths()
export in your Astro pages is used to define which pages should be built for a dynamic route in SSG mode. For each page you return a params
and props
property.
In Astro 2.1, we’ve added two new helpers to infer these types and provide type checking when using these values in your template.
Given the following getStaticPaths()
function:
---// Example: src/pages/blog/[slug].astroexport async function getStaticPaths() { const posts = await getCollection("blog") return posts.map((post) => { return { params: { slug: post.slug }, props: { draft: post.data.draft, title: post.data.title }, } })}---
You could now use the new InferGetStaticParamsType
and InferGetStaticPropsType
helper types to get type definitions for your params
and props
values without needing to define them manually:
import { InferGetStaticParamsType, InferGetStaticPropsType } from "astro"export async function getStaticPaths() { /* ... */}
type Params = InferGetStaticParamsType<typeof getStaticPaths>type Props = InferGetStaticPropsType<typeof getStaticPaths>const { slug } = Astro.params as Params// ^? { slug: string; }const { title } = Astro.props// ^? { draft: boolean; title: string; }
Try Astro 2.1
Thank you to everyone who contributed to this outstanding release. In addition to these new features, there were also a bunch of bug fixes throughout the core packages and integrations. See the complete release notes to learn more.