# Preact Documentation This file contains comprehensive documentation for Preact v10, a fast 3kB alternative to React with the same modern API. Preact is a fast, lightweight alternative to React that provides the same modern API in a much smaller package. This documentation covers all aspects of Preact v10, including components, hooks, server-side rendering, TypeScript support, and more. --- ## Introduction **Description:** How to get started with Preact. We'll learn how to setup the tooling (if any) and get going with writing an application ### Getting Started New to Preact? New to Virtual DOM? Check out the [tutorial](/tutorial). This guide helps you get up and running to start developing Preact apps, using 3 popular options. If you're new to Preact, we recommend starting with [Vite](#create-a-vite-powered-preact-app). #### No build tools route Preact is packaged to be used directly in the browser, and doesn't require any build or tools: ```html ``` The primary drawback of developing this way is the lack of JSX, which requires a build step. An ergonomic and performant alternative to JSX is documented in the next section. ##### Alternatives to JSX Writing raw `h` or `createElement` calls can be tedious. JSX has the advantage of looking similar to HTML, which makes it easier to understand for many developers in our experience. JSX requires a build step though, so we highly recommend an alternative called [HTM][htm]. [HTM][htm] is a JSX-like syntax that works in standard JavaScript. Instead of requiring a build step, it uses JavaScript's own [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, which was added in 2015 and is supported in [all modern browsers](https://caniuse.com/#feat=template-literals). This is an increasingly popular way to write Preact apps, since there are fewer moving parts to understand than a traditional front-end build tooling setup. ```html ``` > **Tip:** HTM also provides a convenient single-import Preact version: > > `import { html, render } from 'https://esm.sh/htm/preact/standalone'` For a more scalable solution, see [Import Maps -- Basic Usage](/guide/v10/no-build-workflows#basic-usage), and for more information on HTM, check out its [documentation][htm]. [htm]: https://github.com/developit/htm #### Create a Vite-Powered Preact App [Vite](https://vitejs.dev) has become an incredibly popular tool for building applications across many frameworks in the past couple of years, and Preact is no exception. It's built upon popular tooling like ES modules, Rollup, and ESBuild. Vite, through our initializer or their Preact template, requires no configuration or prior knowledge to get started and this simplicity makes it a very popular way to use Preact. To get up and running with Vite quickly, you can use our initializer `create-preact`. This is an interactive command-line interface (CLI) app that can be run in the terminal on your machine. Using it, you can create a new application by running the following: ```bash npm init preact ``` This will walk you through creating a new Preact app and gives you some options such as TypeScript, routing (via `preact-iso`), and ESLint support. > **Tip:** None of these decisions need to be final, you can always add or remove them from your project later if you change your mind. ##### Getting ready for development Now we're ready to start our application. To start a development server, run the following command inside your newly generated project folder: ```bash # Go into the generated project folder cd my-preact-app # Start a development server npm run dev ``` Once the server has started, it will print a local development URL to open in your browser. Now you're ready to start coding your app! ##### Making a production build There comes a time when you need to deploy your app somewhere. Vite ships with a handy `build` command which will generate a highly-optimized production build. ```bash npm run build ``` Upon completion, you'll have a new `dist/` folder which can be deployed directly to a server. > For a full list of all available commands and their options, check out the [Vite CLI Documentation](https://vitejs.dev/guide/cli.html). #### Integrating Into An Existing Pipeline If you already have an existing tooling pipeline set up, it's very likely that this includes a bundler. The most popular choices are [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) or [parcel](https://parceljs.org/). Preact works out of the box with all of them, no major changes needed! ##### Setting up JSX To transpile JSX, you need a Babel plugin that converts it to valid JavaScript code. The one we all use is [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Once installed, you need to specify the function for JSX that should be used: ```json { "plugins": [ [ "@babel/plugin-transform-react-jsx", { "pragma": "h", "pragmaFrag": "Fragment" } ] ] } ``` > [Babel](https://babeljs.io/) has some of the best documentation out there. We highly recommend checking it out for questions surrounding Babel and how to set it up. ##### Aliasing React to Preact At some point, you'll probably want to make use of the vast React ecosystem. Libraries and Components originally written for React work seamlessly with our compatibility layer. To make use of it, we need to point all `react` and `react-dom` imports to Preact. This step is called _aliasing._ > **Note:** If you're using Vite (via `@preact/preset-vite`), Preact CLI, or WMR, these aliases are automatically handled for you by default. ###### Aliasing in Webpack To alias any package in Webpack, you need to add the `resolve.alias` section to your config. Depending on the configuration you're using, this section may already be present, but missing the aliases for Preact. ```js const config = { //...snip resolve: { alias: { react: 'preact/compat', 'react-dom/test-utils': 'preact/test-utils', 'react-dom': 'preact/compat', // Must be below test-utils 'react/jsx-runtime': 'preact/jsx-runtime' } } }; ``` ###### Aliasing in Node When running in Node, bundler aliases (Webpack, Rollup, etc.) will not work, as can be seen in NextJS. To fix this, we can use aliases directly in our `package.json`: ```json { "dependencies": { "react": "npm:@preact/compat", "react-dom": "npm:@preact/compat" } } ``` ###### Aliasing in Parcel Parcel uses the standard `package.json` file to read configuration options under an `alias` key. ```json { "alias": { "react": "preact/compat", "react-dom/test-utils": "preact/test-utils", "react-dom": "preact/compat", "react/jsx-runtime": "preact/jsx-runtime" } } ``` ###### Aliasing in Rollup To alias within Rollup, you'll need to install [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias). The plugin will need to be placed before your [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) ```js import alias from '@rollup/plugin-alias'; module.exports = { plugins: [ alias({ entries: [ { find: 'react', replacement: 'preact/compat' }, { find: 'react-dom/test-utils', replacement: 'preact/test-utils' }, { find: 'react-dom', replacement: 'preact/compat' }, { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' } ] }) ] }; ``` ###### Aliasing in Jest [Jest](https://jestjs.io/) allows the rewriting of module paths similar to bundlers. These rewrites are configured using regular expressions in your Jest configuration: ```json { "moduleNameMapper": { "^react$": "preact/compat", "^react-dom/test-utils$": "preact/test-utils", "^react-dom$": "preact/compat", "^react/jsx-runtime$": "preact/jsx-runtime" } } ``` ###### Aliasing in TypeScript TypeScript, even when used alongside a bundler, has its own process of resolving types. In order to ensure Preact's types are used in place of React's, you will want to add the following configuration to your `tsconfig.json` (or `jsconfig.json`): ```json { "compilerOptions": { ... "skipLibCheck": true, "baseUrl": "./", "paths": { "react": ["./node_modules/preact/compat/"], "react/jsx-runtime": ["./node_modules/preact/jsx-runtime"], "react-dom": ["./node_modules/preact/compat/"], "react-dom/*": ["./node_modules/preact/compat/*"] } } } ``` Additionally, you may want to enable `skipLibCheck` as we do in the example above. Some React libraries make use of types that may not be provided by `preact/compat` (though we do our best to fix these), and as such, these libraries could be the source of TypeScript compilation errors. By setting `skipLibCheck`, you can tell TS that it doesn't need to do a full check of all `.d.ts` files (usually these are limited to your libraries in `node_modules`) which will fix these errors. ###### Aliasing with Import Maps ```html ``` See also [Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#recipes-and-common-patterns) for more examples. ------ **Description:** New features and changes in Preact X ### What's new in Preact X Preact X is a huge step forward from Preact 8.x. We've rethought every bit and byte of our code and added a plethora of major features in the process. Same goes for compatibility enhancements to support more third-party libraries. In a nutshell Preact X is what we always wanted Preact to be: A tiny, fast and feature-packed library. And speaking of size, you'll be happy to hear that all the new features and improved rendering fit into the same size footprint as `8.x`! #### Fragments `Fragments` are a major new feature of Preact X, and one of the main motivations for rethinking Preact's architecture. They are a special kind of component that renders children elements inline with their parent, without an extra wrapping DOM element. On top of that they allow you to return multiple nodes from `render`. [Fragment docs →](/guide/v10/components#fragments) ```jsx function Foo() { return ( <>
Something went badly wrong
; } return props.children; } } ``` #### Hooks `Hooks` are a new way to make sharing logic easier between components. They represent an alternative to the existing class-based component API. In Preact they live inside an addon which can be imported via `preact/hooks` [Hooks Docs →](/guide/v10/hooks) ```jsx function Counter() { const [value, setValue] = useState(0); const increment = useCallback(() => setValue(value + 1), [value]); return (foo
, document.body); render(bar
, document.body); // Preact 8.x output:foo
bar
; ``` In order to diff existing children in Preact 8, an existing DOM node had to be provided. ```jsx // Existing markup:foo
, document.body); element = render(bar
, document.body, element); // Preact 8.x output:bar
; ``` In Preact X, `render()` always diffs DOM children inside of the container. So if your container contains DOM that was not rendered by Preact, Preact will try to diff it with the elements you pass it. This new behavior more closely matches the behavior of other VDOM libraries. ```jsx // Existing markup:foo
, document.body); render(bar
, document.body); // Preact X output:bar
So will I
Something went badly wrong
; } return props.children; } } render(Counter: {state.value}
Counter: {value}
Counter A: {value}
I'm a nice counter
Count: {count}
Active theme: {theme}
; } // ...later function App() { return (Window width: {width}
; } render(This is a hint
{error.message}