Preact Preset for Vite

repository·main·Indexed 43 days ago

https://github.com/preactjs/preset-vite

An all-in-one Vite plugin (@preact/preset-vite v2.10.6) to streamline Preact development. It provides HMR via Prefresh, Preact Devtools integration, automatic React compatibility aliasing to preact/compat, and support for static site prerendering.

Tokens
3.5K
Snippets
11
Records
14
Agent score
55%

What's inside Preact Vite Plugin

  1. Install @preact/preset-vite

    main

    Install the @preact/preset-vite package as a development dependency using npm or yarn to enable Preact features in your Vite project.

    npm install --save-dev @preact/preset-vite
    # or
    yarn add -D @preact/preset-vite
  2. How to implement Prerendering

    main

    To use prerendering, follow these steps:

    1. Enable prerendering in the plugin options (enabled: true).
    2. Specify a renderTarget (e.g., '#app') that matches the selector used in your client-side render() call.
    3. Create a prerender() function in a script. This function must be exported and should return an object containing an html property (the rendered string). You can use libraries like preact-render-to-string or preact-iso to generate this.
    4. Expose the script: Either add a <script prerender src="..."> tag to your HTML entrypoint or specify the absolute path using the prerenderScript plugin option.

    The prerender() function can be asynchronous, allowing for data fetching or file system access during the build process.

    import { prerender as ssr } from 'preact-iso';
    
    function App() {
        return <h1>Hello World!</h1>
    }
    
    export async function prerender(data) {
        const { html, links: discoveredLinks } = ssr(<App />);
    
        return {
            html,
            // Optionally add additional links that should be
            // prerendered (that haven't already been)
            links: new Set([...discoveredLinks, '/foo', '/bar']),
            // Optional data to serialize into a script tag for use on the client:
            //   <script type="application/json" id="preact-prerender-data">{"url":"/"}</script>
            data: { url: data.url },
            // Optionally configure and add elements to the `<head>` of
            // the prerendered HTML document
            head: {
                // Sets the "lang" attribute: `<html lang="en">`
                lang: 'en',
                // Sets the title for the current page: `<title>My cool page</title>`
                title: 'My cool page',
                // Sets any additional elements you want injected into the `<head>`:
                elements: new Set([
                    { type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },
                    { type: 'meta', props: { property: 'og:title', content: 'Social media title' } }
                ])
            }
        };
    }
  3. Configure the Preact Vite plugin

    main

    To use the preset, add the preact() plugin to your vite.config.ts or vite.config.js file using defineConfig.

    import { defineConfig } from "vite";
    import preact from "@preact/preset-vite";
    
    export default defineConfig({
      plugins: [preact()]
    });
  4. Configure Prerendering

    main

    The prerender option allows you to enable and configure static site prerendering for your Preact application.

    preact({
      prerender: {
        enabled: true,
        renderTarget: '#app',
        prerenderScript: '/path/to/script.js',
        additionalPrerenderRoutes: ['/404'],
        previewMiddlewareEnabled: true,
        previewMiddlewareFallback: '/index.html'
      }
    })
  5. Configure Babel transformations

    main

    Use the babel option to add plugins, presets, and other configuration to the Babel transformation applied to each JSX/TSX file. Plugins provided here run before built-in transforms like Fast Refresh.

    preact({
      babel: {
        presets: [...],
        // Your plugins run before any built-in transform (eg: Fast Refresh)
        plugins: [...],
        // Use .babelrc files
        babelrc: true,
        // Use babel.config.js files
        configFile: true,
      }
    })
  6. Configure @preact/preset-vite options

    main

    You can customize the behavior of the Preact preset by passing an options object to the preact() plugin function.

    Key features included by default:

    • Hot Module Replacement (HMR) via prefresh.
    • Preact Devtools bridge during development.
    • React Aliasing: Automatically aliases react and react-dom to preact/compat.
    export default defineConfig({
      plugins: [
        preact({ devtoolsInProd: true })
      ]
    });
  7. Configure PreactPluginOptions

    main

    You can pass an options object to preact() to customize its behavior.

    Available Options

    OptionTypeDefaultDescription
    devtoolsInProdbooleanfalseInject devtools bridge in production bundle instead of only in development mode.
    devToolsEnabledbooleantrueWhether to use Preact devtools.
    prefreshEnabledbooleantrueWhether to use prefresh HMR.
    reactAliasesEnabledbooleantrueWhether to alias react and react-dom to preact/compat.
    includeFilterPattern[/[\.[cm]?[tj]sx?$/]RegExp or glob to match files to be transformed.
    excludeFilterPattern[/node_modules/]RegExp or glob to match files to NOT be transformed.
    babelBabelOptionsundefinedBabel configuration applied in both dev and prod.
    jsxImportSourcestring"preact"Import Source for jsx.
    prerenderobject{ enabled: false }Configuration for the prerender plugin.

    Prerender Options

    OptionTypeDescription
    enabledbooleanWhether to prerender your app on build.
    prerenderScriptstringAbsolute path to script containing an exported prerender() function.
    renderTargetstringQuery selector for specifying where to insert prerender result in your HTML template.
    additionalPrerenderRoutesstring[]Additional routes that should be prerendered.
    previewMiddlewareEnabledbooleanIf true, corrects Vite's preview server to use prerendered HTML.
    previewMiddlewareFallbackstringPath to use as a fallback/404 route (e.g., /404).
    import { preact } from '@preact/preset-vite';
    
    preact({
      devtoolsInProd: true,
      reactAliasesEnabled: true,
      prerender: {
        enabled: true,
        prerenderScript: './prerender.js',
        renderTarget: '#app',
        additionalPrerenderRoutes: ['/about', '/contact']
      }
    });
  8. Reference: Prerendering configuration options

    main

    The following options are available within the prerender object:

    OptionTypeDefaultDescription
    enabledbooleanfalseEnables prerendering
    renderTargetstring"body"Query selector for where to insert prerender result in your HTML template
    prerenderScriptstringundefinedAbsolute path to script containing exported prerender() function. If not provided, will try to find the prerender script in the scripts listed in your HTML entrypoint
    additionalPrerenderRoutesstring[]undefinedPrerendering will crawl your site automatically, but you'd like to prerender some pages that may not be found (such as a /404 page), use this option to specify them
    previewMiddlewareEnabledbooleanfalseVite's preview server as of v5 will not use our prerendered HTML documents automatically. This option enables a middleware that will correct this, allowing you to test the result of prerendering locally
    previewMiddlewareFallbackstring/index.htmlFallback path to be used when an HTML document cannot be found via the preview middleware, e.g., /404 or /not-found will be used when the user requests /some-path-that-does-not-exist
  9. Reference: Preset plugin options

    main

    The following options are available for the preact() plugin:

    OptionTypeDefaultDescription
    devtoolsInProdbooleanfalseInject devtools bridge in production bundle instead of only in development mode
    devToolsEnabledbooleantrueInject devtools bridge
    prefreshEnabledbooleantrueInject Prefresh for HMR
    reactAliasesEnabledbooleantrueAliases react, react-dom to preact/compat
    babelobjectSee Babel configuration
    prerenderobjectSee Prerendering configuration
  10. Use the Preact Vite plugin

    main

    The preact plugin (exported as the default or via the preactPlugin named export) integrates Preact into a Vite project. It handles JSX transformation, provides Preact DevTools support, enables HMR via prefresh, and can automatically alias react and react-dom to preact/compat to support React ecosystem libraries.

    import { preact } from '@preact/preset-vite';
    import { defineConfig } from 'vite';
    
    export default defineConfig({
      plugins: [preact()]
    });
  11. Configure the transformHookNamesPlugin

    main

    The transformHookNamesPlugin is a Vite plugin used to assist with Preact DevTools by injecting addHookName calls around specific hook usages (like useState, useReducer, useRef, or useMemo). This helps DevTools identify which variable name is associated with a hook.

    To use this plugin, you must provide a shouldTransform filter function to determine which files should be processed.

    transformHookNamesPlugin({
    	shouldTransform: (id) => id.endsWith('.ts'), // Example filter
    	devtoolsInProd: false,
    	devToolsEnabled: true
    });
  12. Configure the preactDevtoolsPlugin

    main

    The preactDevtoolsPlugin is a Vite plugin used to inject the Preact Devtools bridge or Preact debug utilities into your application. It can be configured via the PreactDevtoolsPluginOptions object.

    Options

    OptionTypeDefaultDescription
    devtoolsInProdbooleanfalseIf true, the devtools bridge will be injected even in production builds.
    devToolsEnabledbooleanCalculatedExplicitly enables or disables the plugin. If not provided, it defaults to true in development and false in production (unless devtoolsInProd is true).
    shouldTransformRollupFilterRequiredA function used to determine which files should be eligible for the injection process.
    import { preactDevtoolsPlugin } from '@preact/preset-vite';
    
    // Example configuration
    export default {
      plugins: [
        preactDevtoolsPlugin({
          devtoolsInProd: false,
          devToolsEnabled: true,
          shouldTransform: (id) => id.includes('src/main.tsx'),
        }),
      ],
    };