Preact is a JavaScript library that describes itself as a fast 3kB alternative to React with the same ES6 API. As a frequent user of React, I’d always wanted to try out Preact and see what it offers, and the differences between Preact and React.
It was developed by Jason Miller to provide a feature set similar to React in a smaller package. Preact has the fastest virtual DOM libraries and diff implementation. Some of its salient features are:
Uber, Lyft, and Housing.com are just a few of the organizations that have migrated to Preact and benefited both in terms of increased performance and reduced size. The case study of Uber is well known. Uber migrated from its native app to a web client that provides an app-like experience via web browsers. The move to Preact ensured that browsers loaded faster, resulting in an increased number of ride requests.
Preact has many tools and libraries to support and extend its functionality. Here are my top 10 picks.
Redux Zero is a lightweight state container based on Redux. Written in TypeScript, it supports not only Preact, but other libraries and frameworks like React, Svelte, and Vue. It is smaller in size and more efficient as it has a single store and no reducers.
Use the NPM command given below to install Redux Zero:
npm i redux-zero
Coding with Redux Zero is simple and straightforward. Follow these steps:
import createStore from "redux-zero";
const initialState = { count: 1 };
const store = createStore(initialState);
export default store;
2. Actions are used to change the state of the store. Create the Action.js file as follows:
export default {
decrement: ({ count }) => ({ count: count - 1 }),
increment: ({ count }) => ({ count: count + 1 })
}
3. As actions are pure functions, they are bound to the store.
import React from "react";
import { connect } from "redux-zero/react";
import actions from "./actions";
const mapToProps = ({ count }) => ({ count });
const s = {
root: { fontFamily: "sans-serif", textAlign: "center" },
btns: { display: "flex", justifyContent: "center" },
btn: { margin: 20 }
};
export default connect(mapToProps, actions)(
({ count, decrement, increment }) => (
<div style={s.root}>
<h1>{count}</h1>
<div style={s.btns}>
<button style={s.btn} onClick={decrement}>
decrement
</button>
<button style={s.btn} onClick={increment}>
increment
</button>
</div>
</div>
)
);
4. Now let’s connect all of these components in the index.js file.
import React from "react";
import { render } from "react-dom";
import { Provider } from "redux-zero/react";
import store from "./store";
import Counter from "./Counter";
const App = () => (
<Provider store={store}>
<Counter />
</Provider>
);
render(<App />, document.getElementById("root"));
Refer to the working code of this example:
## 2\. fpreact: (Functional Preact)fpreact is an alternative API used to create Preact components. The API provides state management similar to redux and facilitates functional programming by removing the use of this.
fpreact is based on elm, which is used to create graphical UIs for web browsers. fpreact uses a domain-specific programming language and is a competitor of React.js and Vue.js.
fpreact is written in and supports Typescript, but can also work with javascript. To install it, use the following NPM command:
npm i -S fpreact preact
Below is the simple ES6 + JSX code for a ‘Hello World’ application:
import { h, render, component } from 'fpreact';
const Msg = {
// You don't have to use a number here.
// You could just as easily use "UPDATE_NAME" or anything else if you desire,
// just make sure each item has a unique value
UpdateName: 0,
};
const Greet = component({
update(model = { name: 'world' }, msg) {
switch (msg.kind) {
case Msg.UpdateName:
return { ...model, name: msg.value };
}
return model;
},
view(model, dispatch) {
return (
<div>
<h1>Hello, {model.name}</h1>
<label>
<span>Name:</span>
<input value={model.name} onInput={dispatch(Msg.UpdateName)} />
</label>
</div>
);
},
});
render(<Greet />, document.body);
Proppy is a JavaScript library used to compose props, and it is only 1.5 kb in size. The props passed to ProppyJS can be used in any component–based UI framework like React, Vue, and Preact.
It also works with the data layer as a props composition. These are some of the benefits of using Proppy:
Here is a simple example of using ProppyJS with Preact:
import { h } from 'preact';
import { compose, withProps, withState } from 'proppy';
import { attach } from 'proppy-preact';
const P = compose(
withProps({ foo: 'foo value' }),
withState('counter', 'setCounter', 0)
);
function MyComponent({ foo, counter, setCounter }) {
return (
<div>
<p>Foo: {foo}</p>
<p>Counter: {counter}</p>
<button onClick={() => setCounter(counter + 1)}>
Increment
</button>
</div>
);
}
export default attach(P)(MyComponent);
ClearX maintains the application state and is an alternative to Redux and MobX. It binds application state to UI components using an interface and provides getters and setters for deep properties of nested data.
React class components and Function UI components work well with ClearX. You can simply install ClearX with the following NPM command:
npm install clearx - save
Follow these steps to use ClearX:
ClearX first creates the stores and then uses the path to set deep properties of data. So they can be defined for non-existing or undefined properties.
import ClearX from `clearx`;
let store = new ClearX({
id: 'Brave Browser',
version: 'v0.68.140',
settings: {
File: true,
Edit: true,
History: true,
Bookmarks: true,
Window: true,
Help: true,
DevTools: true
},
openTabs: 3,
users: [{
email: 'john.doe@test.com',
name: 'John Doe',
age: 300
}, {
email: 'doe.john@test.com',
name: 'Doe John',
age: 50
}]
});
export default store;
The datastore can be of any type.
2. Bind data to the UI store as follows:
Now it can be bound to the class store or selected path of the store using the useState() hook.
import React, { Fragment, useState } from 'react';
import store from './store';
const App = () => {
let [ identity ] = store.paths(['id', 'version']).link(useState());
let [ usersCount ] = store.paths('users.length').link(useState());
let [ openTabs ] = store.paths('openTabs').link(useState());
let [ settings, unlink ] = store.paths({
devTools: 'settings.DevTools',
history: 'settings.History'
}).link(useState());
useEffect(() => unlink, []);
return (
<code>
Id: { identity[0] }
Version: { identity[0] }
openTabs: { openTabs }
UsersCount: { usersCount }
DevToolsEnabled: { settings.devTools }
HistoryEnabled: { settings.history }
</code>
);
}
export default App;
ClearX also provides multiple API’s to operate and find the data as per applications.
Preact-urql uses urql with the Preact core and hooks. It is used to improve the usability and stability of customized GraphQL infrastructure. To start, you need to import a single package from the framework of your choice. But it also has collections of connected parts to extend the application.
When using GraphQL, a primary data layer is created by urql to handle content-heavy pages through “Document Caching” and Normalized caching for data-heavy apps. It creates a user interface using trees of components and elements.
This is an example of Preact-urql where the render() function accepts the tree description and creates structures. It then appends the structure to the DOM element of a parent as a second argument. Thereafter the render() function uses the existing tree and calculates the difference in the outputs of current and previous to update the DOM.
import { render, h } from 'preact';
import { useState } from 'preact/hooks';
/** @jsx h */
const App = () => {
const [input, setInput] = useState('');
return (
<div>
<p>Do you agree to the statement: "Preact is awesome"?</p>
<input value={input} onChange={e => setInput(e.target.value)} />
</div>
)
}
render(<App />, document.body);
Apart from using Preact-CLI, here are some tools to make your coding with Preact much easier.
nwb is a zero-configuration development setup but also supports configuration and plugin modules. It provides a quick development environment for Preact and its components.
nwb provides auto-prefixed CSS, default polyfills, and uses promises for configurations. nwb uses JavaScript and JSX features and provides an environment for tests and optimizes webpack builders. It can be installed using npm as follows:
npm install -g nwb
This is an example of Preact components to whip up a lightbulb.js:
import {h, Component} from 'preact'
export default class Lightbulb extends Component {
state = {
on: false
}
updateChecked = (e) => {
this.setState({on: e.target.checked})
}
render({wattage = 200}, {on}) {
return <div>
<label>
<input type="checkbox" checked={on} onClick={this.updateChecked}/>
{' '}
{wattage}W lightbulb is {on ? 'on' : 'off'}
</label>
</div>
}
}
Use the following command to install essential dependencies and start a webpack development server.
$ nwb preact run Lightbulb.js
✔ Installing preact
Starting Webpack compilation...
Compiled successfully in 3717 ms.
The app is running at http://localhost:3000/
For a production build, use “nwb preact build”:
$ nwb preact build Lightbulb.js
✔ Building Preact app
File size after gzip:
dist\app.b12334ec.js 8.63 KB
nwb provides automatic dependency installations, style preprocessing, rendering the entry module, and hot module replacement along with the development and testing environment.
Rewired allows you to tweak the create-react-app webpack config(s) without the need to eject or create a fork of the react-scripts. It allows you to add plugins, loaders, and all the benefits of the create-react-app command without the restrictions of “no-config.”
Use the following NPM command to install rewired:
npm install react-app-rewired --save-dev
To make changes to config files, you can create config-overrides.js within the root directory.
/* config-overrides.js */
module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
}
+-- your-project
| +-- config-overrides.js
| +-- node_modules
| +-- package.json
| +-- public
| +-- README.md
| +-- src
“Flip” the existing calls of Preact-scripts in npm to start, build, and test. All scripts other than those required to eject can be flipped.
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
}
You can now start and run the server, and set a custom path for config-pverride.js…
"config-overrides-path": "node_modules/some-preconfigured-rewire"
Preact-CLI-postcss will provide the postcss.config.js file and disable the default postcss config so that you can have better control. To install, use the following command:
npm install preact-cli-postcss
It adds your properties to preact.config.js as follows:
const preactCliPostCSS = require('preact-cli-postcss');
export default function (config, env, helpers) {
preactCliPostCSS(config, helpers);
}
Create Preact APP can be used to create Preact apps with no configurations. It is similar to create-react-app, but uses Preact. Some of its important characteristics are:
You can use the below command to set and start the dev-server:
npm install preact preact-compat
This command will create the below folder structure with pre-installed transitive dependencies:
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js
Use the following commands to run your application:
cd my-app
npm start
Preact is gradually gaining popularity over React due to its lightweight nature and faster performance. It gives users the ability to expand its features using the libraries and tools. Many organizations like Uber have migrated to Preact and experienced many benefits making Preact a worthy alternative to React.
#preact #reactjs #javascript #webdev