Preact is a fast, lightweight alternative to React, designed for high performance. With a size of just 3kB, it offers an API closely aligned with React, making it an ideal choice for building modern web applications in resource-constrained environments.
Preact Fundamentals
Introduction to Preact
Preact is a fast, lightweight alternative to React, optimized for performance. At only 3kB, it provides a React-like API, making it perfect for creating modern web applications in environments with limited resources.
Features and Benefits of Preact
- Lightweight: Preact’s core is only 3kB, significantly smaller than React, resulting in faster loading and lower bandwidth usage.
- High Performance: Its compact size and efficient rendering mechanism deliver exceptional performance.
- React Compatibility: Preact’s API mirrors React’s, enabling easy migration from React to Preact.
- Rich Ecosystem: Preact supports most React ecosystem libraries and tools, such as Redux and React Router.
- Ease of Use: Preact’s API is simple and intuitive, making it easy to learn and implement.
Similarities and Differences Between Preact and React
Similarities
- API: Preact’s API closely resembles React’s, including components, state, and props.
- Component-Based: Like React, Preact allows developers to create reusable components.
- Virtual DOM: Preact uses virtual DOM technology to enhance rendering performance.
Differences
- Size: Preact is only 3kB, while React is larger and slower to load.
- Performance: Preact’s smaller footprint often makes it faster than React.
- Features: Preact lacks some of React’s advanced features, like the Context API (available via plugins).
- Community and Ecosystem: React has a larger community and more third-party libraries and tools.
Installing Preact
Install Preact using npm or yarn:
npm install preact
# or
yarn add preactPreact Basic Concepts
Creating Components
Preact components can be either class components or function components, similar to React.
Function Component:
import { h } from 'preact';
const Hello = ({ name }) => {
return <h1>Hello, {name}!</h1>;
};
export default Hello;Class Component:
import { h, Component } from 'preact';
class Hello extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Hello;Rendering Components
Use the render method to mount components to the DOM:
import { h, render } from 'preact';
import Hello from './Hello';
render(<Hello name="World" />, document.getElementById('root'));Component State
Preact components can manage state, similar to React:
import { h, Component } from 'preact';
class Counter extends Component {
state = { count: 0 };
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;Lifecycle Methods
Preact provides lifecycle methods akin to React’s:
import { h, Component } from 'preact';
class LifecycleDemo extends Component {
componentDidMount() {
console.log('Component mounted');
}
componentDidUpdate() {
console.log('Component updated');
}
componentWillUnmount() {
console.log('Component will unmount');
}
render() {
return <div>Check the console for lifecycle logs</div>;
}
}
export default LifecycleDemo;Preact Core Principles
Preact is a fast, lightweight React alternative focused on delivering a similar developer experience with a smaller footprint and higher performance. Its core concepts include component-based development, virtual DOM, and diff algorithms.
Component-Based Development
Function Components
Function components are the simplest form, ideal for stateless, straightforward components.
import { h } from 'preact';
const HelloWorld = () => {
return <h1>Hello, World!</h1>;
};
export default HelloWorld;Class Components
Class components are suited for complex components requiring state and lifecycle methods.
import { h, Component } from 'preact';
class HelloWorld extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default HelloWorld;Component Composition
Components can be composed to build complex UIs.
import { h } from 'preact';
const Header = () => <h1>Header</h1>;
const Footer = () => <h1>Footer</h1>;
const App = () => (
<div>
<Header />
<p>Main content</p>
<Footer />
</div>
);
export default App;Understanding Virtual DOM and Diff Algorithm
Virtual DOM
The virtual DOM is a lightweight JavaScript object representing the DOM structure. It allows frameworks to efficiently manipulate and compute changes in memory before applying them to the actual DOM.
Example:
const virtualDOM = h('div', { id: 'app' }, h('h1', null, 'Hello, World!'));Diff Algorithm
The diff algorithm is central to the virtual DOM, comparing two virtual DOM trees to identify changes and apply only the necessary updates to the real DOM.
Basic Diff Algorithm Steps:
- Node Comparison: Compare the root nodes of two virtual DOM trees. If types differ, replace the entire node.
- Attribute Comparison: If node types match, compare attributes. Update differing attributes.
- Child Node Comparison: Recursively compare child nodes, applying minimal changes.
Example:
// Initial virtual DOM
const oldVNode = h('div', { id: 'app' }, h('h1', null, 'Hello, World!'));
// New virtual DOM
const newVNode = h('div', { id: 'app' }, h('h1', null, 'Hello, Preact!'));
// Diff algorithm to compare and update the real DOM
function diff(oldVNode, newVNode, parent) {
if (!oldVNode) {
parent.appendChild(createElement(newVNode));
} else if (!newVNode) {
parent.removeChild(oldVNode._dom);
} else if (changed(oldVNode, newVNode)) {
parent.replaceChild(createElement(newVNode), oldVNode._dom);
} else if (newVNode.type) {
const oldLength = oldVNode.children.length;
const newLength = newVNode.children.length;
for (let i = 0; i < oldLength || i < newLength; i++) {
diff(oldVNode.children[i], newVNode.children[i], oldVNode._dom);
}
}
}
function changed(node1, node2) {
return typeof node1 !== typeof node2 ||
(typeof node1 === 'string' && node1 !== node2) ||
node1.type !== node2.type;
}
function createElement(vnode) {
const node = document.createElement(vnode.type);
vnode.children.map(createElement).forEach(node.appendChild.bind(node));
return node;
}
// Initial render
const root = document.getElementById('root');
root.appendChild(createElement(oldVNode));
// Update render
diff(oldVNode, newVNode, root);Hello, World! Example
Let’s demonstrate Preact’s basic usage with a “Hello, World!” example.
Step 1: Install Preact
npm install preactStep 2: Create Project Files
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Preact Hello World</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>index.js
import { h, render } from 'preact';
// Create a simple function component
const HelloWorld = () => <h1>Hello, World!</h1>;
// Render the component to the DOM
render(<HelloWorld />, document.getElementById('root'));Step 3: Configure Babel and Webpack
Install Babel and Webpack:
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli webpack-dev-serverCreate the Babel configuration file .babelrc:
{
"presets": [
["@babel/preset-env", { "targets": "> 0.25%, not dead" }],
["@babel/preset-react", { "pragma": "h", "pragmaFrag": "Fragment" }]
]
}Create the Webpack configuration file webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
static: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
resolve: {
alias: {
'react': 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat'
}
}
};Step 4: Build and Run the Project
npm run build
npm startOpen your browser and visit http://localhost:9000 to see “Hello, World!”.
Preact Basic Applications
Installing Preact
Ensure Node.js and npm are installed. Create a new project directory and initialize it:
mkdir preact-app
cd preact-app
npm init -yInstall Preact and related dependencies:
npm install preact
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli webpack-dev-serverConfiguring Babel and Webpack
Create the Babel configuration file .babelrc:
{
"presets": [
["@babel/preset-env", { "targets": "> 0.25%, not dead" }],
["@babel/preset-react", { "pragma": "h", "pragmaFrag": "Fragment" }]
]
}Create the Webpack configuration file webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
static: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
resolve: {
alias: {
'react': 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat'
}
}
};Creating Project Files
Create the HTML file index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Preact App</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>Create the JavaScript file src/index.js
import { h, render } from 'preact';
// Create a simple function component
const HelloWorld = () => <h1>Hello, World!</h1>;
// Render the component to the DOM
render(<HelloWorld />, document.getElementById('root'));Building and Running the Project
Add build and start scripts to package.json:
"scripts": {
"build": "webpack",
"start": "webpack serve"
}Run the following commands to build and start the project:
npm run build
npm startVisit http://localhost:9000 in your browser to see “Hello, World!”.
Understanding the render and h Functions
h Function
The h function is a factory function provided by Preact to create virtual DOM nodes, similar to React’s createElement. It builds a virtual DOM tree, which Preact’s diff algorithm converts into actual DOM operations.
Example:
import { h } from 'preact';
// Create a virtual DOM node
const vnode = h('h1', null, 'Hello, World!');This code generates a virtual DOM node representing <h1>Hello, World!</h1>.
render Function
The render function mounts a virtual DOM tree to the actual DOM, taking a virtual DOM node and a DOM container as arguments.
Example:
import { h, render } from 'preact';
// Create a simple component
const HelloWorld = () => <h1>Hello, World!</h1>;
// Render the component to the DOM
render(<HelloWorld />, document.getElementById('root'));This renders the HelloWorld component into the DOM element with the ID root.
Component-Based Development
Component-based development breaks the UI into reusable components, which can be function or class components. Below is an example of creating and composing components.
Creating Components
Header.js
import { h } from 'preact';
const Header = () => <header><h1>Header</h1></header>;
export default Header;Footer.js
import { h } from 'preact';
const Footer = () => <footer><h1>Footer</h1></footer>;
export default Footer;App.js
import { h } from 'preact';
import Header from './Header';
import Footer from './Footer';
const App = () => (
<div>
<Header />
<main>
<h1>Main Content</h1>
</main>
<Footer />
</div>
);
export default App;Update index.js
import { h, render } from 'preact';
import App from './App';
// Render the App component to the DOM
render(<App />, document.getElementById('root'));



