So this is a React work, why the 💩 are we talking about [Preact][preact]? Let me tell you why! Preact is amazing! Preact is an almost drop in replacement for React that is much smaller in file size while maintaing nearly all the features and actually being faster (or so my limited, flawed benchmarking leads me to believe.) One thing is for sure though, it’s much smaller!

It sounds just better, right? Well, it’s certainly something you and your company should discuss. Preact is just 3KB gzipped; that’s really small! React for comparison’s sake is around 80KB, give or take 10KB. That’s a huge difference! The way Preact is able to achieve a lot of the size difference is by cutting out some of the legacy bits of React, letting browser do more, and focusing on a smaller API.

Speaking of a smaller API, we can’t switch to Preact wholesale as-is right now; we’re using the React and ReactDOM package everywhere. In addition, we’re using propTypes (Preact doesn’t have those) and the createClass syntax (Preact only supports ES6 classes and stateless functional components.)

So instead we’re going to drop in the preact-compat library which backfills those APIs at the cost of adding 5KB to your payload; still a win. preact-compat gets you started on your migration; eventually you want to drop it and just be on Preact.

So we’re going to super quick migrate to Preact for the client side. In webpack.config.js, add:

// inside resolve
alias: {
  react: 'preact-compat',
  'react-dom': 'preact-compat'
},

// inside 'babel-loader' loader
include: [
  path.resolve('js'),
  path.resolve('node_modules/preact-compat/src')
]

The include parts is just telling babel-loader to only run on files that are in the js directory (our code) or in the preact-compat directory. We should have done this sooner since this will speed up your build by not running on every file in node_modules.

The alias bit is telling webpack that everytime in our app we ask for react or react-dom, to actually give it preact-compat (which itself encompasses Preact.) Now build your app for production and compare! In my local env, I’m seeing a difference of 96.2KB vs 228KB for production builds. Not bad!!

Our server more-or-less works as is. It’s not ideal; honestly you’d want Preact doing both server and client work, but this is good for now. If you want to make it work, you’ll need to make Babel alias React to Preact instead of Webpack since that runs both client and server side whereas Webpack doesn’t.