Newsletter
Join the Community
Subscribe to our newsletter for the latest news and updates
Out-of-box MPA plugin for Vite that generates multiple entries using only one template.
vite-plugin-virtual-mpa is a Vite plugin that generates multiple HTML entries for multi-page applications from a single EJS template using virtual files.
vite-plugin-virtual-mpa is an open-source Vite plugin (by emosheeep) that adds out-of-the-box MPA support with a built-in EJS template engine and virtual entry files. It takes a pages configuration (each page with a name, an optional entry JS file, optional EJS data, and an optional custom filename like fruits/apple.html) and produces built HTML files at those configured paths. The plugin runs inside Vite's build and dev server, automatically populating rollupOptions.input and the dev/preview server history-fallback rewrites.
data option, and VITE-prefixed environment variables are automatically injected..html files need to exist in the source tree.filename like fruits/apple.html, which is relative to build.outDir, letting you control exactly where the built file lands.base and the page-name-to-filename map; you can override them with rewrites and previewRewrites.scanDirs; subdirectory names become page names, and entryFile and a filename function customize the output.pages config or restart the dev server on file add/change/remove events, with include/exclude filters following Rollup.createFilter.transformIndexHtml to modify generated HTML, receiving the page context so you can inject tags or alter markup per page.html-minifier-terser, gated on the htmlMinify option (default false).fruits/apple.html, the filename option gives you that control without post-build file-moving scripts.apple, banana, strawberries, each with its own entry and data (e.g. a title), and generate all of them from one template with different content.scanOptions.scanDirs at a folder like src/fruits, set entryFile: 'index.js', and every subdirectory instantly becomes a page, with output paths controlled by the filename callback.rewrites or previewRewrites in the connect-history-api-fallback format so refreshes reach the right virtual HTML file.Install the plugin with pnpm add -D vite-plugin-virtual-mpa, then add createMpaPlugin to your vite.config.ts and pass a pages array. The plugin generates a virtual module for each page using the template and the page's data, wires up rollupOptions.input from the filename values, and injects default history-fallback rules derived from base and the page map. During development, these virtual files are served in memory; during vite build, they are emitted to the configured output paths.
createPages helper.rewrites, they override the automatically generated default rules, so you must maintain them manually; pages created through scanOptions cannot receive per-page data injection through that feature (you'd need to define those pages manually for custom data).Yes, it's an open-source Vite plugin distributed on npm and publicly hosted on GitHub, with no paid tiers mentioned. You can install it with pnpm add -D, npm install, or yarn add.
Yes, the README explicitly states the plugin doesn't limit the technology stack and works with Vue, React, or any other framework, because it only handles the HTML entry generation and the entry JS script.
Set the filename property in that page's configuration, for example filename: 'fruits/apple.html'. It defaults to ${name}.html and is resolved relative to build.outDir.
Yes, through the scanOptions option. You provide scanDirs, and optionally entryFile and a filename function; the subdirectory names become page names. This auto-generates pages but cannot pass per-page data to the template.
rewrites?Your rewrites value replaces the default history-fallback rule that the plugin would otherwise generate from your pages configuration. You must make sure your rules cover all the routes you want to resolve.
