Skip to content

The-CodeCave/vite-plugin-ssg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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-ssg

Usage

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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published