DEV Community

Cover image for How to use Preact with Astro
Jannik Baranczyk
Jannik Baranczyk

Posted on

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.

Preact is a "Fast 3kB alternative to React with the same modern API". It's smaller than React but shares most of it's features (Hooks, Context), so you can write normal React code but benefit from better performance.

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 
Enter fullscreen mode Exit fullscreen mode

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']
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

You can import the component like this:

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

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

<Counter client:load />
Enter fullscreen mode Exit fullscreen mode

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!

Discussion (0)