vite-plugin-virtual-html
raw JSON → 1.2.7 verified Mon Apr 27 auth: no javascript
Vite plugin for flexible multi-page app (MPA) development, allowing HTML files to be placed anywhere in the project and configured via a pages map. Current stable version is 1.2.7, released periodically since 2020. Key differentiators: eliminates Vite's default HTML root restriction, provides dev-server interception for seamless MPA development, supports EJS templating with custom render functions, and includes automatic Rollup input configuration. Compared to vanilla Vite MPA, it offers a configurable pages structure similar to @vue/cli's pages option, with additional features like injectCode and urlTransformer.
Common errors
error TypeError: virtualHtml is not a function ↓
cause Using CJS require() with ESM-only version >=1.2.0
fix
Switch to ESM import or use dynamic import()
error [vite]: Rollup failed to resolve import "..." from "..." ↓
cause HTML file not found during build; often caused by missing file or incorrect paths in pages config
fix
Verify all pages paths are correct and files exist; also ensure extraGlobPattern excludes dist
error Error: ENOENT: no such file or directory, open '/path/to/project/root/index.html' ↓
cause Dev mode: requested HTML file is not in pages config or path is wrong
fix
Add the HTML file path to the pages config or ensure the requested URL matches a configured page
error Plugin page config: index is not a valid page config ↓
cause pages entry must be a string (path) or an object with 'template' key; using other type
fix
Ensure each page value is either a string path or an object: { template: 'path', data: {...} }
Warnings
breaking Dropped support for CJS in v1.2.0; require() will fail ↓
fix Use ESM imports (import virtualHtml from 'vite-plugin-virtual-html') or downgrade to v1.1.x
gotcha html files must exist on disk in dev mode? No, but if missing, dev server returns 404 (since v1.1.20) ↓
fix Ensure all configured HTML files exist or handle 404 gracefully
gotcha build.rollupOptions.input is overridden by plugin; manual input config may conflict ↓
fix Remove manual input config; plugin auto-generates it from pages
deprecated option 'page' was renamed to 'template' in v0.2.0 ↓
fix Use 'template' key for HTML file path in page objects
gotcha injectCode only works when specifying html file pattern with '*' (globbing) ↓
fix Use '*' as key in injectCode to apply to all HTML files, or specify individual file paths
breaking viteConfig.appType is set to 'custom' by default since v1.2.4 (useCustom: true), which disables Vite's SPA fallback ↓
fix Set useCustom: false to revert to pre-1.2.4 behavior (appType auto-detected)
gotcha Build copies HTML files to project root before building; if process crashes, root may get polluted ↓
fix Clean up root HTML files manually if build is interrupted; known limitation
Install
npm install vite-plugin-virtual-html yarn add vite-plugin-virtual-html pnpm add vite-plugin-virtual-html Imports
- default (plugin function) wrong
const virtualHtml = require('vite-plugin-virtual-html')correctimport virtualHtml from 'vite-plugin-virtual-html' - VirtualHtmlOptions (type) wrong
import { VirtualHtmlOptions } from 'vite-plugin-virtual-html'correctimport type { VirtualHtmlOptions } from 'vite-plugin-virtual-html' - RenderFunction (type)
import type { RenderFunction } from 'vite-plugin-virtual-html'
Quickstart
// vite.config.ts
import { defineConfig } from 'vite';
import virtualHtml from 'vite-plugin-virtual-html';
export default defineConfig({
plugins: [
virtualHtml({
pages: {
index: '/src/pages/index/index.html',
about: '/src/pages/about/about.html',
},
indexPage: 'index',
data: { title: 'My App' },
}),
],
});
// Create HTML files somewhere in project
// /src/pages/index/index.html
// /src/pages/about/about.html
// Run `npm run dev` – plugin serves HTML from configured paths.
// Run `npm run build` – plugin configures Rollup input and copies files.