How to use Preact with Astro

I recently tried to use Preact with Astro. Since I found no decent tutorial on how to use those two together, I decided to write one.

If you don't know Astro, you should definitely check it out. Astro is a new modern static site builder that allows us to use React/Preact, Svelte and Vue components all together, while shipping only the absolute necessary client-side JavaScript, using a technique called "Partial Hydration". That results in really fast sites with less JavaScript. They just released v0.21.0, which introduced a new, faster compiler written in Go a new build engine powered by Vite.

So how can I use Preact components with Astro?

The fastest way to do this, is to select Preact as your framework in the Astro CLI when you setup a new project. This tutorial presupposes that you want to add Preact to an existing Astro project.

First you need to install a renderer for Preact, and the Preact library itself.

npm install --save-dev @astrojs/renderer-preact preact

Then you need to add the just installed renderer to the Astro config file, astro.config.mjs. When you open it, the renderers property should be an empty Array. Add the @astrojs/renderer-preact package to the Array.

renderers: ['@astrojs/renderer-preact']

That's all you need to setup Preact with Astro! 🎉

Now you can write your Preact components as .jsx or .tsx files and import them to your Astro pages.

For example, this is how you would write a simple Counter component in TypeScript (.tsx):

// /src/components/Counter.tsx

import { useState } from 'preact/hooks'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div className='counter'>
      <button onClick={() => setCount(count - 1)} disabled={count === 0}>
        -
      </button>
      <h2>{count}</h2>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

You can import the component like this:

---
// /src/pages/index.astro

import Counter from '../components/Counter.tsx'
---

<Counter client:load />

Tip: The client:load snippet you see above comes from Astro's Partial Hydration. If we leave this away, Astro would only render the components markup, without any interactivity, to ship less client-side JavaScript. You can learn more about Partial Hydration in the official Astro Docs

Happy hacking!

17