I had an old blog written in Jekyll that I started in 2013 but it hadn’t been updated in an embarassingly long time so I decided to start so fresh and so clean clean. Here we are, a new website built with Astro. Unless you’ve been living under a rock (or if you’re not a web dev) you’ve probably heard of it.
One of the coolest things it brings to the table is it’s “Component Islands” architecture, so like think of the various components your app might have: header, navigation, sidebar, footer, etc. Some of these components could be mostly static like your footer but you may also have something like an image carousel component that’s interactive. In astro you can mix and match your UI framework, hypothetically you could have a header written in Svelte, a sidebar written in Vue, and an image carousel written in React. Although I’m not quite sure why anyone in their sane mind would do that. Anyways, the biggest benefit of astro islands is performance, most of your website is converted to fast static html and the javascript is only loaded for the individual components that actually need it.
My favorite, and newish part of Astro is the ability to use mdx files which is like markdown but with jsx, so if I want I can build little components and slap them in my blog post, for example:
or like make this super fun game where the goal is to click the button 10 times:
That’s pretty awesome, right? Astro gives you multiple client directives:
client:load
load and hydrate the component js immediately on page loadclient:idle
load and hydrate the component js once the page is done with its initial loadclient:visible
load and hydrate the component js once the component has entered the user’s viewportclient:media
loads and hydrates the component js once a certain CSS media query is metclient:only
like load except skips html server-rendering completely
For example, with my Dadjoke component, I set it to client:visible
so the javascript doesn’t load until the component reaches the user’s viewport.
<Dadjoke client:visible />
and you’re probably wanting my amazing Dadjoke component, so here you go:
import { useState } from "react";
const Dadjoke = () => {
const [joke, setJoke] = useState < string > "";
const generateDadJoke = () => {
fetch("https://icanhazdadjoke.com/", {
headers: {
Accept: "application/json",
},
})
.then(res => res.json())
.then(data => setJoke(data.joke));
};
return (
<>
<button className="btn" onClick={generateDadJoke}>
{joke ? "👴 Generate Another Dad Joke 🤪" : "👴 Generate Dad Joke 👴"}
</button>
{joke && <blockquote>{joke}</blockquote>}
</>
);
};
export default Dadjoke;