Javascript

Upgrading from Astro 2 to Astro 4

Tom VanAntwerp
3 min read
Tom - Upgrading from Astro 2 to Astro 4
This article was written over 18 months ago and may contain information that is out of date. Some content may still be relevant, but please refer to official documentation for the latest information.

Upgrading from Astro 2 to Astro 4

Astro is building fast. Right on the heels of their version 3 launch on August 30th, Astro version 4 launched on December 6th, 2023. They've built so fast, that I didn't even have a chance to try 3 before 4 came out! But the short time between versions makes sense, because the two releases are very complementary. Many Astro features introduced in version 3 as experimental are made stable by version 4. If, like me, you're looking at a two-version upgrade, here's what you need to know about Astro 3 and 4 combined.

View Transitions

Astro makes it easy to include animated transitions between routes and components with the <ViewTransitions /> component. You can add it to the <head> of specific pages, or to your site-wide <head> to be enabled across the entire site. No configuration is required, but you'll probably still want to configure it.

Adding <ViewTransitions /> between pages effectively turns your site into a single-page application, animating in and out content on route change rather than downloading a new statically generated HTML document. You can further customize how specific components animate in and out with the transition:animate property. If you don't want client side routing for a specific link, you can opt out for that link with the data-astro-reload property.

Image Optimization

The way Astro works with images has changed a lot from version 2. If you were using @astrojs/image, then updating how you handle images is probably going to be the most time-consuming part of your Astro migration.

Astro's <Image /> and <Picture /> components have had API changes, which will require you to make changes in your usage of them. You should definitely check out the full image migration guide in the Astro docs for all of the details. But some of the details you should be aware of:

  • @astrojs/image is out, astro:assets is in
  • You get image optimization when you import images inside /src. This can change your entire image src referencing strategy. Optimization only works for images imported from inside /src, so you might want to relocate images you've been keeping inside the /public directory.
  • Importing an image file no longer returns the path as a string, and an ImageMetadata object with src, width, height, and format properties. If you need the previous behavior, add ?url to the import path.
  • Markdown documents can reference image paths inside /src for automatic image optimization, no need to use <Image /> in MDX nor reference the root relative paths of images in the /public directory.
  • The <Image /> and <Picture /> components have changes to properties. For example, aspectRatio is no longer a valid property because it is inferred from the width and height of images. A new pictureAttributes property lets you do things like add a CSS style string.
  • You can use a helper image schema validator in your content collection schemas.

Dev Toolbar

The Dev Toolbar is a new local development feature to help developers work with their interactive islands and to integrate with other tools. The Inspect option highlights what parts of the page are interactive, and lets you examine them. You can view their props and even open them directly in your editor. Audit checks for accessibility issues, such as missing alt attributes in images. And the Menu lets you use specific integrations. Currently only Storyblok and spotlight are available, but you can expect more integrations in the future. And if you don't want to wait, you can also extend the Dev Toolbar yourself with their API.

If you don't like the Dev Toolbar, you can turn it off in the CLI with astro preferences disable devToolbar.

Conclusion

Astro has added a lot of cool features in 2 major back-to-back releases, and you should absolutely consider upgrading if you're still on version 2. Be prepared to modify how you've handled images, but also get excited to play with view transitions!

About the author

Tom VanAntwerp

Tom VanAntwerp

Senior Software Engineer

Keep reading

View all posts →

Astro: Do You Even Need JavaScript? with James Quick

James Quick, content creator and co host of the Compressed FM podcast talks about the evolution of Astro, a powerful static site generator that we should all get familiar with. He talks in depth about the framework and where the framework may head in the future. Astro has been making waves in the web development community. It has evolved over time, and is now competing with major meta frameworks. But with its unique features and excellent developer experience, Astro offers developers a fresh perspective on building websites and applications. Astro v3 brings a host of exciting features to the table. James shares Astro supports the View Transition API, which allows for smoother page transitions and a seamless user experience. He and Dustin talk about Astro's image optimization component, which optimizes images for performance without compromising quality. One of the standout features of Astro is its island architecture. James explains how this architecture enables developers to seamlessly integrate other frameworks, providing unparalleled flexibility and versatility in web development. This unique approach empowers developers to leverage the strengths of multiple frameworks and create truly dynamic and powerful websites. James shares his thoughts on Astro’s new Qwik integration, highlighting its potential impact on web development workflows. Qwik integration opens up new possibilities and advantages for developers, streamlining their development process and enabling them to build faster and more efficiently. As web development continues to evolve, Astro stands as a powerful tool for developers seeking flexibility, performance, and enhanced user experiences. Listen to the full podcast episode here: https://modernweb.podbean.com/e/jamesquick/...

2 mins
AstroJavaScript

Leveraging Astro's Content Collections

Astro’s content focused approach to building websites got a major improvement with their v2 release. If you’re not familiar with Astro, it is web framework geared towards helping developers create content rich websites that are highly performant. They enable developers to use their favorite UI framework to build components leveraging an islands architecture, and provide the end user with just the minimal download needed to interact with the site and progressively enhance the site as needed. Astro is a fantastic tool for building technical documentation sites and blogs because it provides markdown and MDX support out of the box, which enables a rich writing experience when you need more than just your base markdown. The React Docs leverage MDX help the documentation writers provide the amazing experience we’ve all been enjoying with the new docs. In Astro v2, they launched Content Collections, which has significantly improved their already impressive developer experience (DX). In this post, we’re going to look into how Astro (and other frameworks) managed content before Content Collections, what Content Collections are, and some of the superpowers Content Collections give us in our websites. How Content is Managed in Projects? A little bit of history… Content management for websites has always been an interesting challenge. The question is typically: where should I store my content and manage it? We have content management systems (CMS), like WordPress, that people have historically and currently use to quickly build out websites. We also have Headless CMS like Contentful and Sanity that enable writers to enter their content, and then bring on developers to build out the site utilizing modern web frameworks to display content. All these solutions have enabled us to manage our content in a meaningful way, especially when the content writers aren’t developers or technical content writers. However, these tools and techniques can be limiting for writers who want to use rich content objects. For example, in the React Docs, they use Sandpack to create interactive code samples. How can we achieve these same results in our projects? The Power of MDX This is where MDX comes in. We can create re usable markdown components that allow writers to progressively enhance their blog posts with interactive elements without requiring them to write custom code into their article. In the example below, we can see the HeaderLink component that allows the writer to add a custom click handler on the link that executes a script. While this is a simple example, we could expand this to create charts, graphs, and other interactive elements that we normally couldn’t with plain markdown. Most CMS systems haven’t been upgraded to handle MDX yet, so to provide this type of experience, we need to provide a good writing experience in our codebases. The MDX Experience Before Content Collections, we had two main approaches for structuring content in our projects. The first was to write each new document as a markdown or MDX page in our pages directory, and allow the file system router to handling the routing and define pages for us. This makes it easy to map the blog post to a page quickly. However, this leads to a challenge of clutter where, as our content grows, our directory will grow. This can make it harder to find files or articles unless a clear naming convention is utilized which can be hard to enforce and maintain. It also mixes our implementation details and content documents which can cause some organizational mess. The second approach is to store our content in a separate directory, and then create a page to collect the data out of this directory and organize it. This is the approach the React Docs take. This model has the clear advantage that the content and implementation details are separated. However, in these models, the page responsible for bringing the content together becomes a glue file trying to do file system operations, and joining data, in a logical way. This can be very brittle as any refactor could cause breakage in this model. Astro enables doing this using their Astro.glob API, but it has some limitations we’ll go over a little later. So… What Are Content Collections? Content Collections enable you to better manage content files in your project. They provide a standard for organizing content, validating aspects of the content, and providing some type saftey features to your content. Content Collections took the best parts of the separate directory approach, similar to the React Docs, and did their best to eliminate all the cons of this approach. You can leverage Content Collections by simply moving your content into the src/content directory of your project under a folder of the type of content it represents. Is it a blog post? Stick it in blog. Working with a newsletter? Toss it in newsletter. These folders are the “collections” . You can stick either .md or .mdx files in these folders, and those are your “content entries” . Once your content is in this structure, you can now use Astro’s new content APIs to query your data out in a structured way, and start using its superpowers. Supercharging your Content! Query Your Content like a Database Astro’s content API provides two functions: getCollection() and getEntryBySlug() for querying your data. getCollection() has 2 arguments: the collection name and a filter function. This enables you to fetch all the content in a collection and filter to only specific files/entries based on parameters in the files frontmatter of your choosing. getEntryBySlug() takes in the collection name and file slug and returns the specific requested file. What’s particularly meaningful about these functions is that they return content with full TypeScript typings so you can validate your entries. You don’t need to write file system connecting logic and manage it yourself anymore. Configuring Content Entry Types Collection entries can be configured to meet specific requirements. In src/content/config.ts, you can define collections and their schemas using Zod and then registering those with the framework as demonstrated below. This is extremely powerful because now Astro can handle validating our markdown to ensure all the required fields are defined, AND it returns those entities in their target format through the content API. When you used the Astro.glob API, you would get all frontmatter data as strings or numbers requiring you to parse your data for other standard primitives. With this change, you can now put dates into your frontmatter and get them out as date objects via the content API. You can now remove all your previous validation and remapping code and convert it all to Zod types in your collection config. But instead of having to run linters and tests to find the issues, the Astro runtime will let you know about your collection errors as you’re creating them through your IDE, or server runtime. Content Collection Gotchas Content collections can only be top level folders in the src/content directory. This means you can’t nest collections. However, you can organize content within a collection using subdirectories, and use the filtering feature of the content API to create sub selections. The main use case for this would be i18n translations for a collection. You can place the content collections in a directory for that language, and use the filter function to select those at runtime for display. The other main "gotcha" is routing. Before, we were leveraging the file based router to handle rendering our pages. But now, there are no explicit routes defined for these pages. In order to get your pages to render properly, you’ll need to leverage Astro’s dynamic route features to generate pages from your entries. If you’re in static mode (the default), you need to define a getStaticPaths() function on your specified catch all route. If you’re in SSR mode, you’ll need to parse the route at runtime, and query for the expected data. Some Notes on Migrating from File Based Routing If you had a project using Astro before v2, you probably want to upgrade to using content collections. Astro has a good guide on how to accomplish this in their docs. There’s two main gotchas to highlight for you. The first is that layouts no longer need to be explicitly defined in the markdown files. Because you’re shifting content to use a specified layout, this property is unnecessary. However, if you leave it, it will cause the layout to be utilized on the page causing weird double layouting , so be sure to remove these properties from your frontmatter. The second is that the content API shifts the frontmatter properties into a new data property on the return entries. Before, you might have had a line of code like post.frontmatter.pubDate. This now needs to be post.data.pubDate. Also, if this was a stringified date before, you now need to stringify the date to make it behave properly, e.g. post.data.pubDate.toDateString(). Finally, you can remove any custom types you made before, because now you can get those directly from your collection config. In summary… Astro Content Collections are a great way to manage your content and websites, especially if they’re content focused and rich. I’ve put together some code demonstrating all the patterns and techniques described in this post that you can check out here. At This Dot, we love utilizing the right tool for the right job. Astro is increasingly becoming one of our favorites for content site projects. We use it for our open source projects framework.dev and starter.dev and are always considering it for additional projects....

Dustin Goodman8 mins
AstroJavaScript

Using Astro on framework.dev

Have you heard of Astro? It's an exciting, if still experimental, static site generation framework that allows you to author components using your choice of framework and completely control if and when javascript is shipped to the client. If you would like to learn more, I wrote an introductory blog post about it. Considering how new and experimental Astro is, you might be wondering what it's like to actually try to build a website with it. Well, you're in luck because we chose to build react.framework.dev in Astro, and I'm here to tell you how it went. Some background When I was first presented the pitch for the framework.dev project, it had the following characteristics: 1. It was going to be primarily a reference site, allowing users to browse static data. 2. It should be low cost, fast and accessible. 3. Because it was a small internal project, we were pretty free to go out on a limb on our technology choices, especially if it let us learn something new. At the time, I had recently heard exciting things about this new static site generator called "Astro" from a few developers on Twitter, and from cursory research, it seemed perfect for what we had planned. Most of the site was going to be category pages for browsing, with search existing as a bonus feature for advanced users. Astro would allow us to create the whole site in React but hydrate it only on the search pages, giving us the best of the static and dynamic worlds. This plan didn't quite survive contact with the enemy (see the "ugly" section below) but it was good enough to get the green light. We also picked vanilla extract as a styling solution because we wanted to be able to use the same styles in both React and Astro and needed said styles to be easily themeable for the different site variants. With its wide array of plugins for different bundlers, it seemed like an extremely safe solution. Being able to leverage Typescript type checking and intellisense to make sure theme variables were always referenced correctly was certainly helpful. But as you'll see, the journey was much less smooth than expected. The Good Astro did exactly what it had promised. Defining what static pages would be generated based on data, and what sections of those pages would be hydrated on the client, was extremely straightforward. The experience was very similar to using NextJS, with the same system of file system paths defining the routing structure of the site, augmented with a getStaticPaths function to define the generation of dynamic routes. However, Astro is easier to use in many ways due to its more focused feature set: Very streamlined and focused documentation. No potential confusion between static generation and server rendering. All code in Astro frontmatter is run at build time only, so it's much easier to know where it's safe to write or import code that shouldn't be leaked to the client bundle. No need to use special components for things like links, which greatly simplifies writing and testing components. Our Storybook setup didn't have to know about Astro at all, and in fact is running exactly the same code but bundling it with its own webpack based builder. Choosing what code should be executed client side is so easy that describing it is somewhat anticlimactic: However, this is a feature that is simply not present in any other framework, and it gives a site very predictable performance characteristics: each page loads only as much Javascript as has been marked as needing to be loaded. This means that each page can be profiled and optimized in isolation, and increases in complexity in other pages will not affect it. For example, we have kept the site's homepage entirely static, so even when it shares code with dynamic areas like search, the volume of that code doesn't impact load times. The Bad Although we were pleasantly surprised by how many things worked flawlessly despite Astro being relatively new, we were still plagued by a number of small issues: A lot of things didn't work in a monorepo. We had to revert to installing all npm libraries in the root package rather than using the full power of workspaces, as we had trouble with hoisting and path resolution. Furthermore, we had to create local shims for any component we wanted to be a hydration root, as Astro didn't handle monorepo imports being roots. We were hit multiple times with a hard to trace issue that prevented hydration from working correctly with a variety of errors mostly relating to node modules being left in the client bundle. The only way to fix this was to clear the Snowpack cache and build the site for production before trying to start the dev server. You can imagine how long it took to figure out this slightly bizarre workaround. Astro integration with Typescript and Prettier was pretty shaky, so the experience of editing Astro components was a bit of a throwback to the days before mature Javascript tooling and editor integrations. I'm very thankful that we had always intended to write almost all of our components in React rather than Astro's native format. We also hit a larger hurdle that contributed to the above problems' remaining issues for the lifetime of the project: Astro moved from Snowpack to Vite in version 0.21, but despite vanilla extract having a Vite plugin, we were unable to get CSS working with the new compiler. It's uncertain whether this is an issue with Astro's Vite compiler, or whether it's down to vanilla extract's Vite plugin not having been updated for compatibility with Vite's new (and still experimental) SSR mode that Astro uses under the hood. Whatever the reason, what we had thought was a very flexible styling solution left us locked in version 0.20 with all its issues. The lesson to be learnt here is probably that when dealing with new and untested frameworks it's wise to stick to the approaches recommended by their authors, because there's no guarantees of backwards compatibility for third party extensions. The Ugly As alluded to in the introduction, our plans for framework.dev evolved in ways that made the benefits of Astro less clear. As the proposed design for the site evolved, the search experience was foregrounded and eventually became the core of every page other than the homepage. Instead of a static catalogue with an option to search, we found ourselves building a search experience where browsing was just a selection of pre populated search terms. This means that, in almost all pages, almost all of the page is hydrated, because it is an update results as you type search box. In these conditions, where most pages are fully interactive and share almost all of their code, it's arguable that a client side rendering SPA like you'd get with NextJS or Gatsby would be of equal or even superior performance. Only slightly more code would have to be downloaded for the first view and subsequent navigation would actually require less markup to be fetched from the server. The flip side of choosing the right tool for the job is that the job can often change during development as product ideas are refined, and feedback is incorporated. However, even though replacing Astro with NextJS would be fairly simple since the bulk of the code is in plain React components, we decided against it. Even Astro's worst case is still quite acceptable, and maybe in the future, we will add features to the site which will be able to truly take advantage of the islands of interactivity hydration model. Closing thoughts Astro's documentation does not lie. It is a very flexible and easy to use framework with unique options to improve performance that is also still firmly in an experimental stage of its development. You should not use it in large production projects yet. The ground is likely to shift under you as it did with us in the Snowpack to Vite move. The team behind Astro is now targeting a 1.0 release which will hopefully mean greater guarantees of backwards compatibility and a lack of major bugs. It will be interesting to see what features end up making it in, and whether developer tools like auto formatting, linting and type checking are going to also be finished and supported going forward. Without those quality of life improvements, Astro has still been an exciting tool to test out, which has made me think differently about the possibilities of static generation. With them, it might become the only SSG framework you will need....

Jae Anne Bach Hardie6 mins
AstroJavaScriptReact

Building Web Applications using Astro - What makes it special?

I have recently been working on a site built from the ground up using Astro and even in the early state its in, I've been able to see the amazing possibilities it opens up in web development. So let me give you a tour of what makes it special....

Jae Anne Bach Hardie6 mins
AstroStatic Site Generators