{"id":15493,"library":"vite-prerender-plugin","title":"Vite Prerender Plugin","description":"vite-prerender-plugin is a Vite plugin designed to perform server-side rendering (prerendering) of web applications to static HTML during the build process. This is particularly useful for improving initial page load performance and SEO for sites that don't require full server-side rendering on every request. The current stable version is `0.5.13`, with minor updates released somewhat regularly to address bug fixes and ensure compatibility with newer Vite versions, currently supporting Vite 5.x through 8.x. A key differentiator of this plugin is its highly flexible approach, being an extraction of the prerendering functionality from the Preact ecosystem's `@preact/preset-vite` and WMR. It delegates the actual rendering logic to the user, who must provide an exported `prerender()` function within a specified script. This function can be synchronous or asynchronous, allowing for data fetching and file system access, and is expected to return an object containing an `html` property with the rendered string. The plugin then injects this HTML into the main document at a configurable `renderTarget` selector, and can automatically discover and prerender additional routes.","status":"active","version":"0.5.13","language":"javascript","source_language":"en","source_url":"https://github.com/preactjs/vite-prerender-plugin","tags":["javascript","typescript"],"install":[{"cmd":"npm install vite-prerender-plugin","lang":"bash","label":"npm"},{"cmd":"yarn add vite-prerender-plugin","lang":"bash","label":"yarn"},{"cmd":"pnpm add vite-prerender-plugin","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core build tool that the plugin integrates with; specified as a peer dependency.","package":"vite","optional":false}],"imports":[{"note":"Vite plugins are typically consumed as ESM modules in `vite.config.ts` or `vite.config.js`.","wrong":"const { vitePrerenderPlugin } = require('vite-prerender-plugin');","symbol":"vitePrerenderPlugin","correct":"import { vitePrerenderPlugin } from 'vite-prerender-plugin';"},{"note":"Import types for plugin configuration options for enhanced TypeScript support.","symbol":"PrerenderOptions","correct":"import type { PrerenderOptions } from 'vite-prerender-plugin';"},{"note":"Import types for the expected return value of the `prerender` function.","symbol":"PrerenderResult","correct":"import type { PrerenderResult } from 'vite-prerender-plugin';"}],"quickstart":{"code":"/* === 1. Install dependencies === */\n// npm install vite vite-prerender-plugin\n\n/* === 2. vite.config.ts === */\nimport { defineConfig } from 'vite';\nimport { vitePrerenderPlugin } from 'vite-prerender-plugin';\nimport { resolve } from 'path';\n\nexport default defineConfig({\n  plugins: [\n    vitePrerenderPlugin({\n      renderTarget: '#app', // Query selector for where to insert prerender result\n      prerenderScript: resolve(__dirname, './prerender.ts'), // Absolute path to your prerender script\n      additionalPrerenderRoutes: ['/about', '/contact', '/404'], // Routes not automatically discovered\n    }),\n  ],\n  build: {\n    // Ensure build output is suitable for static hosting\n    // For this example, no special SSR options are needed beyond the plugin.\n  }\n});\n\n/* === 3. prerender.ts === */\n// This script runs in a Node.js-like environment during the build process.\n// You would typically use your framework's renderToString method here.\n\ninterface PrerenderResult { html: string; }\n\nexport async function prerender(url: string): Promise<PrerenderResult> {\n  let content = '';\n  switch (url) {\n    case '/':\n      content = '<h1>Home Page</h1><p>Welcome to the prerendered app!</p><a href=\"/about\">About</a>';\n      break;\n    case '/about':\n      content = '<h1>About Us</h1><p>Learn more about our mission.</p><a href=\"/\">Home</a>';\n      break;\n    case '/contact':\n      content = '<h1>Contact Us</h1><p>Get in touch with us.</p>';\n      break;\n    case '/404':\n      content = '<h1>404 - Page Not Found</h1><p>The page you requested does not exist.</p>';\n      break;\n    default:\n      content = '<h1>Dynamic Route</h1><p>This content was prerendered for: ' + url + '</p>';\n      break;\n  }\n  // Simulate an app mounting into a div with id 'app'\n  return { html: `<div id=\"app\">${content}</div>` };\n}\n\n/* === 4. index.html === */\n<!-- In your public/index.html -->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite Prerender Example</title>\n</head>\n<body>\n    <div id=\"app\"><!-- Prerendered content will be injected here --></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n</body>\n</html>\n\n/* === 5. src/main.ts (client-side entrypoint) === */\n// import './style.css'; // Optional: Basic styling\n\nconst app = document.querySelector<HTMLDivElement>('#app');\n\n// Only hydrate or render if the content is not already prerendered\nif (app && !app.innerHTML) {\n  app.innerHTML = `\n    <h1>Client-side Hydration</h1>\n    <p>This content is loaded dynamically if prerendering fails or for SPAs.</p>\n    <button id=\"counter\">count is 0</button>\n  `;\n  let count = 0;\n  document.getElementById('counter')?.addEventListener('click', () => {\n    count++;\n    document.getElementById('counter')!.textContent = `count is ${count}`;\n  });\n}","lang":"typescript","description":"Shows how to configure `vite-prerender-plugin` in `vite.config.ts`, define a `prerender.ts` script for generating HTML, and prerender basic and dynamically added routes. Includes a minimal `index.html` and client-side `main.ts` for context."},"warnings":[{"fix":"Ensure your `vite.config.ts` includes the `prerenderScript` option pointing to an absolute path, or that your `index.html` contains a `<script prerender src=\"...\">` tag, and that the specified script exports an `async function prerender(url: string): Promise<{html: string}>`.","message":"The plugin requires a `prerender` function to be explicitly exported from a script, specified either via a `<script prerender>` attribute in your HTML or the `prerenderScript` plugin option. Failure to provide this will result in prerendering not occurring.","severity":"gotcha","affected_versions":">=0.5.0"},{"fix":"Verify that `renderTarget` (e.g., `'#app'`) matches the selector used in your client-side entrypoint (e.g., `document.querySelector('#app')`).","message":"The `renderTarget` plugin option must precisely match the query selector where your client-side application mounts. Incorrect configuration will lead to the prerendered content not being injected correctly into your HTML.","severity":"gotcha","affected_versions":">=0.5.0"},{"fix":"Ensure your installed Vite version matches the peer dependency range specified by `vite-prerender-plugin`, currently `5.x || 6.x || 7.x || 8.x`. Upgrade or downgrade Vite as needed.","message":"Vite peer dependency updates. Starting from `0.5.9`, the plugin explicitly requires Vite v5.x or newer, and since `0.5.13`, it supports Vite up to v8.x. Using incompatible Vite versions will result in build errors or unexpected behavior.","severity":"breaking","affected_versions":">=0.5.9"},{"fix":"If experiencing issues with `magic-string` and Yarn on `0.5.9`, upgrade `vite-prerender-plugin` to `0.5.10` or newer to resolve the dependency resolution problem.","message":"In version `0.5.9`, `magic-string` was briefly moved to a peer dependency, which could cause Yarn-specific issues with duplicate installs or resolution problems. It was reverted to a regular dependency in `0.5.10`.","severity":"gotcha","affected_versions":"0.5.9"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Upgrade `vite-prerender-plugin` to version `0.5.10` or newer. This issue was resolved by reverting `magic-string` to a regular dependency.","cause":"`magic-string` was briefly a peer dependency in `0.5.9`, causing resolution issues, particularly with Yarn's stricter dependency handling.","error":"Cannot find module 'magic-string' (or similar Yarn dependency tree issues)"},{"fix":"This issue was addressed in version `0.5.12`. Upgrade `vite-prerender-plugin` to `0.5.12` or later to apply the fix.","cause":"An internal error handling source maps or stack traces when a filename was unexpectedly missing during the build process.","error":"Cannot read properties of undefined (reading 'filename') in stack trace"},{"fix":"Verify that the `prerenderScript` path in `vite.config.ts` is absolute and correct. Confirm that the specified script explicitly exports the `prerender` function and that it returns an object with a non-empty `html` string. Also, ensure your `renderTarget` option matches your client-side app's root element ID/class.","cause":"The `prerenderScript` path is incorrect, the specified script does not export an `async function prerender(url: string): Promise<{html: string}>`, or the `renderTarget` option does not match your application's mount point.","error":"Application not prerendered / blank content (during build or in output HTML)"}],"ecosystem":"npm"}