Discovering Preact

Save user’s data with a lighter alternative to React

A look at how Preact can cut the fat and still deliver

4 minute read()
An illustration of a person glancing at their phone in-between the Preact logo and there words "Discovering Preact"

This post is also available in different formats so you can read on the go or share it around!

Thank https://www.drawkit.io/ by @JamesDaly90 for the slick illustration in this title card

React has changed the way we start web projects, it’s become my framework of choice and for good reason. I appreciate JSX and how it looks similar enough to HTML for it to be approachable. Many like the flexibility that React offers when creating reusable components. The rich ecosystem and community built around React is what I love most. Up until recently, I had no reason to not use React when starting a new project but as much as I love using React — it can be a weighty framework for smaller projects and that’s why I decided to investigate Preact.

What is Preact and why should I use it?

It’s put most eloquently by the Preact website as a “Fast 3kB alternative to React with the same modern API”. To put it into perspective, React is closer to 45kB (minified and gzipped). Although it may not seem like a lot, I think Preact makes sense for a many projects because it can save your user’s time and money. You might not bat an eye at users having to download at the very least 45kB of JavaScript to experience your website, it’s a small price to pay for the features you can provide. Unfortunately, not everyone is on an ultra fast connection or high powered device. Depending on who your target audience is, you might want to tailor your experience to them. If your users are going to be viewing your site on the go using mobile data, maybe even on a low-end device, you can be kind to their patience and their data cap by saving them those bytes.

Trying out Preact for the first time

Below is a short clip of the demo interaction I put together to try out Preact. The demo uses Preact as the view framework, preact-router for URL routing and I also used the HiQ CSS framework for the first time to apply some form styling with zero effort.

A clip showing the basic demo interaction we’re building with Preact

Getting started

Getting started with Preact on a new project is easy but it does depend on how you like to work, I like to use Parcel as it’s a no-fuss bundler and makes creating quick projects a breeze.

To get started quickly:

  1. npm install preact
  2. Update your babel file
a code snippet showing how plugin-transform-teact-jsx can be setup in a babel config
  1. Start using it, below is the the entrypoint for the app.
import { h, render } from "preact"
import App from "./containers/App"

if (process.env.NODE_ENV === "development") {
  import("preact/debug")
}

render(<App />, document.body, document.body.lastElementChild)

There are a few minor differences to how you’d normally set up a React entrypoint. The first is the inclusion of preact/debug which is added when developing so we can use React Dev Tools with Preact. The next change is how the render works, we can choose the body to render out <App /> and the third argument is the node we want to replace — this means that when hot reloading, it will replace the body rather than appending it.

How to write a Preact component

A huge selling point for Preact is its compatibility with the React API, therefore it stands to reason that writing a Preact component is almost identical to a standard React component. You have access to the standard lifecycle methods you’d be familiar with in React 15 which means converting to Preact could be as simple as changing the import statement from import React, { Component } from 'react'; to import { h, Component } from 'preact';

import { h, Component } from "preact"
import Login from "./Login"
import UserProfile from "./UserProfile"
import Home from "../components/Home"
import { Router, route } from "preact-router"
import { Link } from "preact-router/match"
import Auth from "../services/auth"

class App extends Component {
  routeChange = e => {
    if (e.url.startsWith("/user/")) {
      if (!this.state.isLoggedIn) route("/", true)
    }
  }

  setLoggedIn = isLoggedIn => {
    this.setState({ isLoggedIn })
  }

  render() {
    return (
      <div>
        <div style={{ backgroundColor: "#efefef" }}>
          <div className="container nav-container">
            <nav>
              <ul>
                <li>
                  <Link activeClassName="active" href="/">
                    Home
                  </Link>
                </li>
              </ul>
              <ul>
                <li>
                  {Auth.isLoggedIn ? (
                    <Link href="/user/profile">Profile</Link>
                  ) : (
                    <Link activeClassName="active" href="/login">
                      Login
                    </Link>
                  )}
                </li>
              </ul>
            </nav>
          </div>
        </div>
        <div className="container">
          <Router onChange={this.routeChange}>
            <Home path="/" />
            <Login path="/login" onLogin={() => this.setLoggedIn(true)} />
            <UserProfile path="/user/profile" />
          </Router>
        </div>
      </div>
    )
  }
}

export default App

The job of the *App *is to manage routing between components and check if the user is logged in. The preact-router library was simple to use and could easily be swapped out if needed. You’ll notice you have access to this.setState() like React as well.

If you’d like to see some more code, take look at the project source.

Differences between React and Preact

Once I had the project setup, I decided to attempt to convert it to React. This was relatively simple except for the routing. After using preact-router, I found the API less obtrusive and easier to understand what was going on. I much prefer, <Login path="/login" /> than the react-router version: <Route path="/login" component={Login} />. Passing props is easier as well, you simply add it to the component rather than using a render prop.

Preact takes a more native approach to HTML which I like, you don’t need to remember the subtle differences when adding attributes to elements like you do with React. No more htmlFor="" just use the HTML attribute for="", this goes for className="" and class="" as well (for this project I stuck with className to reduce the number of changes when making the React version).

I made a pull request to show the differences between react-router in the React version and preact-router in the original Preact version of the project.

Diff between React and Preact

Take a look at the React branch of the repository to see the full list of changes.


My thoughts on Preact

Overall I think Preact is really cool, it takes the same great API I enjoy using and offers a lighter experience with some great benefits. One of which is size, this has a greater impact on mobile browsing which is an important factor to consider when developing a web app. Below are is a side by side comparison of Preact and React simulated on mobile (although it’s not as accurate as real-world device testing, it’s a good approximation). The key metric which I think is important to take away is the script bootup time, it’s important to remember that the longer it takes for a web page to load, the quicker they’ll leave.

Performance matric showing preact as being much fater than react in weight, bootup time, main thread work cost and total byte weight

_A comparison between React and Preact from Stefan Krause’s excellent benchmarking efforts —  https://www.stefankrause.net/wp/

When to choose Preact?

Everything is a matter of opinion and circumstances. Whether to adopt Preact depends on a variety of factors that only you can determine.

  • Mobile: If your target audience is primarily on lower end devices or mobile connections then Preact could be a nice alternative that offers many of the benefits React does.
  • You’re starting a new project: The worst case scenario is that you encounter something you need React for and simply replace it, the API is almost identical.
  • Quicker time to interact: You have an existing app that could benefit from some speed up and a lighter bundle size. You can try migrating your project to Preact, it’s not as simple as a drop-in replacement but it’s pretty close. There is even a compatibility library called preact-compat for that very purpose. Take a look at the official site for how to make the switch.

I am happy I finally gave Preact a go and I will continue to use it when starting small projects. I like the fact that Preact uses the same API as React so you can jump in quickly without having to start from day zero. The benefits of Preact come in the form of smaller bundle sizes and better performance for your end users. It’s a worthwhile consideration to choose Preact for your next project so you can deliver a leaner app without too much extra investment.

Seth Corker

A Fullstack Software Engineer working with React and Django. My main focus is JavaScript specialising in frontend UI with React. I like to explore different frameworks and technologies in my spare time. Learning languages (programming and real life) is a blast.