vite-plugin-ssg
v0.1.0
Published
A Vite plugin for static site generation with React and island architecture
Maintainers
Readme
vite-plugin-ssg
A Vite plugin for static site generation with React and island architecture (partial hydration).
Features
- Static Site Generation - Pre-render React pages to static HTML at build time
- Island Architecture - Only hydrate interactive components, reducing JavaScript payload
- Image Optimization - Automatic image compression and modern format conversion (WebP/AVIF)
- CSS Extraction - Per-page CSS bundles with Tailwind CSS support
- Firebase Hosting - Automatic rewrite configuration for Firebase
- Dev Middleware - Simulates hosting rewrites during development
Installation
npm install vite-plugin-ssgUsage
Vite Configuration
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { ssgPlugin } from 'vite-plugin-ssg';
export default defineConfig({
plugins: [
react(),
ssgPlugin({
pages: ['src/pages/HomePage.tsx', 'src/pages/blog'],
config: {
outDir: 'dist/static',
baseUrl: '/static',
},
hosting: {
firebaseJson: './firebase.json',
},
}),
],
});Page Component
// src/pages/HomePage.tsx
import type { SsgOptions } from 'vite-plugin-ssg';
import { Island } from 'vite-plugin-ssg';
export const ssgOptions: SsgOptions = {
slug: 'home',
routeUrl: '/',
Head: () => (
<>
<title>My Home Page</title>
<meta name="description" content="Welcome to my site" />
</>
),
context: async (children) => {
const { StaticRouter } = await import('react-router-dom/server');
return <StaticRouter location="/">{children}</StaticRouter>;
},
};
export default function HomePage() {
return (
<div>
<h1>Welcome</h1>
<Island component="components/InteractiveWidget" props={{ count: 0 }} />
</div>
);
}Island Component
// src/components/InteractiveWidget.tsx
'use island';
import { useState } from 'react';
export default function InteractiveWidget({ count }: { count: number }) {
const [value, setValue] = useState(count);
return <button onClick={() => setValue(v => v + 1)}>{value}</button>;
}API
ssgPlugin(options)
Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| pages | string \| string[] | Required | Page files or folders to generate |
| config.outDir | string | 'dist/static' | Output directory |
| config.baseUrl | string | '/static' | Base URL for assets |
| config.srcDir | string | 'src' | Source directory |
| config.images.enabled | boolean | true | Enable image optimization |
| config.images.formats | string[] | ['webp'] | Output formats |
| config.images.quality | number | 80 | Image quality (1-100) |
| config.css.minify | string | 'lightningcss' | CSS minifier |
| config.js.minify | string | 'terser' | JS minifier |
| hosting.firebaseJson | string | - | Path to firebase.json |
| verbose | boolean | false | Enable verbose logging |
SsgOptions
Export this from page components to enable static generation:
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| slug | string | Yes | Output filename (e.g., 'home' → home.html) |
| routeUrl | string | No | Route URL for react-router |
| Head | ComponentType | No | Component for <head> content |
| context | ContextWrapper | No | Wrap page with providers |
Island
Component for marking interactive islands:
<Island
component="path/to/Component" // Relative to src/
props={{ key: 'value' }} // Must be JSON-serializable
/>License
MIT
