React, Preact and Inferno quick comparison

Javier Marquez
May 2, 2018 · 7 min read

I don’t have very clear what UI library should I use for PassPill project yet.

I have created projects using React and Preact successfully and after having a look at Inferno, I really wanted to give it a try. Its source code is really easy to read and understand, and even if it’s not as lightweight as Preact, Inferno is still a feather weight library and they say that it’s really fast too.

So I have installed Inferno into PassPill and adapted the app to make it work. It wasn’t much effort, but I stumbled upon the same problem that with Preact: react-hot-loader (RHL) is not working with them.

We can still use webpack dev server with hot reloading, but I am already used to the way RHL updates just the changed components on the fly, preserving their state, and an automatic full reload of the app feels like a pain now.

So I am decided to port RHL to preact and inferno, and to make things simpler I have created a repo with everything that is needed to achieve it:

react-preact-inferno-hot-boilerplate is called :)

The goal is having one app, one single source code, and 3 webpack setups and they should work exactly the same. To do so, we need Preact and Inferno’s compatibility layers, so they are in the game too.

Make RHL work for Preact or Inferno is still a work in progress, (we were lucky enough to get the attention of the libraries’ mantainers, and it will be ready really soon), but some facts came out from the tests that I wanted to share in this quick comparison.

Setting up react-hot-loader

Before starting the comparison, we need an common environment where all the three libraries can run. Our target is make RHL work for all of them, so the first thing to do is to configure our app to use it.

We will need to install webpack and use its development server with hot replacement activated. In top of that, we will use babel to transform our JavaScript files.

Minimum requirements to run our React/Preact/Inferno app

The fact of having a common configuration is great, they are not just sharing the same API, but also the development tools! It’s really nice to know that in case that we wanted to switch libraries in the middle of the development process, we wouldn’t have much problems.

We will write ES2015 code and jsx, and we’ll configure babel-loader to translate all our new fancy code into JavaScript that can be understood by any browser:

A piece of our webpack.config.js with babel configuration

We can see that there are 2 plugins related to hot reloading in our setup. One plugin for webpack and other for babel.

Webpack’s HotModuleReplacementPlugin will send a signal to our app when we update any source file, and the app is reloaded automatically. That’s working for react, preact and inferno.

Babel’s react-hot-loader/babel plugin is the one provided by RHL. When we change any source file, it creates a special bundle update that is understood by the RHL component in our app. That update replaces only the changed parts, without a full reload, preserving application and component’s state. This “magic” way of refreshing our components only work with React. Preact and inferno will ignore the changes if we use it. You can see more about this in the library comparison below.

There is one last thing to make RHL work. In our root component we need to:

import { hot } from ‘react-hot-loader’

And using hot to wrap the root component, see the App.js file.

export default hot(module)(App)

Setting up React

React is the big guy here, so the other libraries are adapted to be compatible with it. Let’s have a look to what we need to make React work, starting with the dependencies:

React dependencies in our package.json

You might be thinking, why don’t we just react-create-app to start? For this comparison we just need the minimum to make React work, and we will be comparing what’s needed for the other libraries too, so we want to pay attention to what we install :)

We can start now our development server, and we will get the following message in the console:

Console bundle information from webpack’s dev server

2.76MB for this tiny tiny application is a lot, specially when our app source code before compilation is smaller than 1KB!

Most of that weight is due to the development tools and when running webpack in production mode it will be gone.

Let’s see how big is the bundle if we compile the code for production. We can see the production configuration file if we want to know the details on how.

Running webpack in production mode shows a big reduction of bundle’s size

That’s better. In production mode the React app reduces its size more than a 95%. The bundle source map is only loaded when we open browser’s dev tools, so our app’s users won’t get that hit either.

That’s what it’s needed to get an app running with React and RHL. The result is great, as the app will change as we update its source files:

When we update the source, the component gets updated preserving state

Setting up Preact

Preact is the most lightweight library of the comparison, it’s very well tested in production and it’s awesome how simple is to make it work in an application that is already using React. We don’t need to change any of the code, just install preact and its compatibility layer:

Our package.json

And then we need to config webpack to let it know that everytime that in our code we say React we actually mean Preact:

We override our webpack resolve configuration to point to preact-compat

That’s all, our app should work right now using Preact and we can feel that in our bundle:

Preact’s development bundle saves more than 1MB compared to React’s one

1MB less than React it’s a huge difference, but we need to keep in mind that React in development mode contains a lot of tools for debugging and comments that help developers to control what’s going on at any circumstance.

But where Preact really brights is at production bundle size:

This is what we like!! 🙌

As we said at the introduction, react-hot-loader is not working well with preact, although we hope they we play along soon. We can still use webpack dev server’s hot updates to refresh the browser when we made some change, but no state preservation then:

Our state is gone on save, even if we get hot updates

Setting up Inferno

I love to have a look at the internals of the libraries. I am not especially a tidy programmer, but I like to see how people organize their code and what I can learn (steal) from them.

Inferno source code is beautiful and it’s easy to understand, something hard to achieve when building a complex library like this one. That’s a plus for me, because I like to know what’s happening when something just doesn’t work.

So let’s give it a try. The steps for getting ready are similar to Preact’s ones. First we need to install the tool and its compatibility layer with React:

Some more dependencies than Preact

So many dependencies to install for the sake of modularity, but I bet you will need all of them if you are migrating from a living React application.

We need to tell webpack about how to fake React using Inferno as we did with Preact:

Hey, React is not really React, it’s Inferno!

It’s really cool that we can switch among libraries so easily! Now our app it’s using Inferno.js and, even if it won’t change our developing experience, it’s a big change internally. Let’s see how it affect to our bundle size:

Inferno bundle size in development mode
Inferno bundle size in production mode

We can’t use react-hot-loader with Inferno yet, but we can use webpack’s hot module replacement, the same way we saw with Preact.

Bundle size wars

Bundle size is important when we are talking about web development, but JavaScript can be used in other environments where the app is loaded locally and we might prefer the big support and community that React provides.

This was just a quick bundle comparison, if we want to dig on what’s making our bundle that big there are many webpack tools that can help us. Have a look at this article by Jannik Hell.

This article is part of the PassPill Project that wants to share the whole development of a web app. As part of the project we will be testing different libraries to discover what’s the one that better adapts to our needs.

If you like this kind of articles, don’t forget to follow our publication and @passpillio in twitter. If you love them, now you can support PassPill on Patreon… be the first! :)