Things I like about Astro
Jan 24, 2023
Astro is a new static site generator. Here is why I like it
Tags:
Astro is the latest static site generator to land on the scene. After hearing about it for a while I finally decided to give it a try and found a lot of things to like. While there are many frameworks for building static sites here some reasons I will continue watching the Astro framework going forward.
Static First and the Islands Architecture
Astro lets you build your site using modern front-end frameworks but doesn’t make the assumption that you are planning on using JavaScript at all. With the emergence of modern component frameworks the inclusion of JavaScript became mandatory for every page. The entirety of the framework needs to be included just to render the page even when only small sections of the page need it.
Astro is built with the Islands Architecture in mind. Most sites are static pages with many components, but only a handful need interactivity. Astro works with this in mind and uses partial hydration to only add JavaScript to the parts of the page needed for interaction. By default Astro ships zero JavaScript and makes you the developer tell it when and where JavaScript is needed. By stripping out all the unused JavaScript you can decrease the time to interactivity (TTI) on your site and make your SEO overlords happy.
So many things out of the box
There is easy support for so many things out of the box. With their integrations you get the following out of the box with minimal configuration:
- TypeScript Support
- Markdown and JSON Support
- CSS preprocessing
- TailwindCSS
- Optional choice of UI frameworks (speaking of which)
Bring your own framework (BYOF)
Astro is the framework that doesn’t make you choose a framework. While there are many new frameworks that allow you build sites with static site generation (SSG) or server-side rendering (SSR) a lot of them only support a certain component framework: NextJS for React, NuxtJS for Vue, SvelteKit for Svelte
.
With various integrations Astro is framework agnostic and allows you to use many popular UI frameworks together. As of this post, there is support for: React, Vue, Svelte, SolidJS, Preact, Lit and AlpineJS
. You can mix and match components from all your favorite frameworks to your hearts content. Whether that is a smart idea or not, Astro leaves that decision up to you.
Similar with styling Astro also has a variety of ways to style your site. You can write the styles directly in the component or use CSS Modules, SCSS, Tailwind, PostCSS, etc. There several options and the choice is yours.
Brings over great features from other frameworks
Coming from React I found several features included in Astro that are a joy to use. They took some great features that exist in other component frameworks and brought them over. Some of my favorite features in Astro components are:
Slots
Astro took slots from Vue and Svelte and included it as a feature. Coming from React I really like slots. Although React has props.children
it doesn’t have a concept of named children. If you wanted to create a component that accepts a component(s) to be put in specific spots separate from the other children, you would normally declare it in the props.
// Wrapper.jsx
const Wrapper = (props) => {
const { Header, Footer, data, children } = props;
// do something with data
return (
<>
<Header />
<div>
{/* some other html */}
</div>
{children}
<Footer />
</>
)
};
While the above works it doesn’t draw a clear separation of what props are meant to be the contents and what is supposed to be state.
---
// Wrapper.astro
const { data } = Astro.props;
// do something with data
---
<div>
<slot name="header">
This is the fallback content in case "header" slot is missing
</slot>
<div>
{/* some other html */}
</div>
{/* every other child passed to component goes into this default slot */}
<slot />
<slot name="footer">
fallback content in case "footer" slot is missing
</slot>
</div>
---
// Page.astro
import Wrapper from "../components/Wrapper.astro";
---
<Wrapper data={"really important data"}>
<h1 slot="header">The header</h1>
<h1 slot="footer">The footer</h1>
<p>
The rest of this goes in default slot even if out of order.
The Wrapper component handles where to place the named slots.
<p/>
</Wrapper>
With slots you can pass all the children into the default placeholder or you can use named slots so the component can place them in designated areas. With slots there is a cleaner separation of contents vs state that is easy to differentiate.
Scoped Styles
Like Svelte, Astro also adopts the idea of scoped styling so that styles declared in your component are isolated that that component alone. It’s veryt similar to React styled-components
out of the box. While not the craziest feature, sometimes it’s nice to have these things available without managing dependencies.
Top Level Await
Astro allows top-level await and executes your script at build time and passes in the returned data to your components. It reduces a lot of boilerplate code and the need to wrap everything in an async function. It runs at build time so it’s a like combining getServerSideProps
and getStaticProps
in NextJS without need to declare it.
---
// ProductPage.astro
import ProductCartForm from '../components/ProductCartForm.jsx';
const { id } = Astro.props;
const response = await fetch(`https://db.com/api/product/${id}`);
const data = await response.json();
const product = data.results[0];
---
<!-- Data fetched at build can be rendered in HTML -->
<h1>Product</h1>
<h2>{product.name}</h2>
<p>{product.description}</>
<!-- Data fetched at build can be passed to components as props -->
<ProductCartForm client:load product={product} />
Final Thoughts
I haven’t seen everything Astro has to offer but from what I’ve seen there is a lot to like. At it’s current stage it is geared more toward content focused sites instead of large web apps. While a bit niche at the moment it will be interesting to see how it changes going forward. It’s still an early stage framework that I’ll be watching. Astro just released version 2.0 with a bunch of interesting new features (i.e. support for hybrid rendering similar to NextJS).