React Native for web is awesome because not only can you reuse all of the dope native Expo packages like expo-camera and react-native-gesture-handler, but you can also use any of the neat things coming out of the React/web community to create blazingly fast websites.
A great example of this is the library Preact by Jason Miller! Preact is a light-weight (~3kb) alternative to React.
When building a web-only project setup is simple, you can just replace React with Preact and start coding right away, but React Native for web is a little bit more complicated.
Because RNWeb uses many different React features we have to really push Preact to its limits to get it working with Expo for web. Luckily it's still pretty simple to setup.
Before Preact
Before we cover the how, let's talk about why you might want to use Preact. If you create a standard Expo web project (at the time of writing this article), the bundle size will look something like the report below.
β 60.75 KB Gzipped
After Preact
If you configure your project to use Preact instead of React, the bundle will reduce drastically! This means your website will load faster and work much better for users with poor internet connections or low-end devices.
β 27.98 KB Gzipped
β½οΈ Getting Started
To use Preact with React Native for web, you'll need to install the packages and alias them to React.
π‘ The most updated info is in the Expo docs: Using Preact
- Install Preact (requires Preact 10+):
yarn add preact-responder-event-plugin preact
- or
npm install --save preact-responder-event-plugin preact
- Create a custom Webpack config for the Expo CLI to use:
- Run
expo customize:web
- Select
webpack.config.js
- Run
- Modify the Webpack config to use Preact instead of React:
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = async (env, argv) => {
const config = await createExpoWebpackConfigAsync(env, argv);
// Add more aliases
config.resolve.alias = {
...config.resolve.alias,
// Use Preact aliases
react$: 'preact/compat',
'react-dom$': 'preact/compat',
// Fix the responder system which react-native-web depends on
'react-dom/unstable-native-dependencies$': 'preact-responder-event-plugin',
};
// Optionally you can enable the bundle size report.
// It's best to do this only with production builds.
if (env.mode === 'production') {
config.plugins.push(new BundleAnalyzerPlugin({
path: 'web-report',
}));
}
return config;
};
- Running
expo build:web
will now use Preact instead of React. This means you'll now have a significantly smaller bundle! π
Drawbacks
To achieve a smaller bundle size Preact has to cut a few features. For instance they don't support synthetic events. Another major drawback is that usage with React Native isn't very clear, if you're building a universal app you may want to consider using the same version of React across web and mobile. For more information on issues using Preact with React Native for web, please refer to this issue react-native-web#1219 (link courtesy of Max Thirouin)
π That's all
Thanks for reading, that's all I've got for you today. Let me know if you enjoyed this article, and reach out if you have any more questions!
Top comments (4)
Didn't know about preact! Thank you!
It's a really awesome package, I'm super excited to have it as part of the Expo web ecosystem now!
Noob question:
Why is Preact only mentioned under the umbrella, if you will, of RNWeb, but not standard React Native (mobile)?
As far as I know, Preact is so small because it tries to re-use many of the things a browser already brings, so it's not as portable as React.