A lightweight, framework-agnostic SPA prerendering library for generating SEO-friendly static HTML pages.
npm install spa-prerender-staticA lightweight TypeScript library for prerendering Single Page Applications (SPAs) with SEO optimization. Generate static HTML files for your SPA routes with proper meta tags and Open Graph data.
- 🚀 Prerender SPA routes to static HTML
- 🎯 SEO optimization with meta tags generation
- 📱 Open Graph and Twitter Card support
- 🗂️ Structured data (JSON-LD) support
- 📦 TypeScript support with full type definitions
- ⚡ Zero dependencies (besides Node.js built-ins)
``bash`
npm install spa-prerender-static
`typescript
import { prerender, generateSEOTags } from "spa-prerender-static";
// Define your routes with SEO configuration
const routes = [
{
path: "/",
tags: {
title: "My App - Home",
description: "Welcome to my amazing single page application",
url: "https://myapp.com",
keywords: "spa, javascript, webapp",
},
},
{
path: "/about",
tags: {
title: "About - My App",
description: "Learn more about our company and team",
url: "https://myapp.com/about",
author: "My Company",
},
},
];
// Prerender your SPA
prerender({
routes,
template: "./template.html",
dist: "./dist",
render: (route) => {
// Your SPA rendering logic here
return
;
},
});
`API Reference
$3
Main function to prerender your SPA routes.
Parameters:
-
options (PrerenderOptions): Configuration object
- routes (RouteConfig[]): Array of routes to prerender
- template (string): Path to HTML template file
- dist (string): Output directory for static files
- render (function): Function that renders route contentExample:
`typescript
prerender({
routes: [{ path: "/", tags: { title: "Home", description: "Welcome" } }],
template: "./public/template.html",
dist: "./build",
render: (route) => ,
});
`$3
Generate SEO meta tags from configuration.
Parameters:
-
options (SEOTagOptions): SEO configurationReturns:
-
string: HTML meta tagsExample:
`typescript
const tags = generateSEOTags({
title: "My Page",
description: "Page description",
url: "https://example.com",
image: "https://example.com/image.jpg",
keywords: "example, page",
canonical: "https://example.com/page",
robots: "index, follow",
schema: {
"@context": "https://schema.org",
"@type": "WebPage",
name: "My Page",
},
});
`Types
$3
`typescript
interface SEOTagOptions {
title: string;
description: string;
author?: string;
url?: string;
image?: string;
keywords?: string;
canonical?: string;
robots?: string;
ampUrl?: string;
schema?: Record;
}
`$3
`typescript
interface RouteConfig {
path: string;
tags: string | SEOTagOptions;
}
`$3
`typescript
interface PrerenderOptions {
routes: RouteConfig[];
template: string;
dist: string;
render: (route: RouteConfig) => string;
}
`HTML Template
Create an HTML template with placeholders that will be replaced during prerendering:
`html
%TITLE% %LINKS%
%APP%
`Placeholders:
-
%TITLE% - Page title
- %APP% - Rendered app content
- %LINKS% - SEO meta tagsUsage Examples
$3
`typescript
import { prerender } from "spa-prerender-static";const routes = [
{ path: "/", tags: { title: "Home", description: "Welcome home" } },
{
path: "/products",
tags: { title: "Products", description: "Our products" },
},
];
prerender({
routes,
template: "./template.html",
dist: "./public",
render: (route) => {
// Simulate SPA routing
const content = route.path === "/" ? "Home content" : "Products content";
return
;
},
});
`$3
`typescript
import { prerender, generateSEOTags } from "spa-prerender-static";const routes = [
{
path: "/blog/my-first-post",
tags: {
title: "My First Post - My Blog",
description: "This is my first blog post about web development",
url: "https://myblog.com/blog/my-first-post",
image: "https://myblog.com/images/post1.jpg",
keywords: "blog, web development, tutorial",
author: "John Doe",
canonical: "https://myblog.com/blog/my-first-post",
schema: {
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: "My First Post",
author: {
"@type": "Person",
name: "John Doe",
},
datePublished: "2024-01-01",
},
},
},
];
prerender({
routes,
template: "./template.html",
dist: "./dist",
render: (route) =>
,
});
`$3
`typescript
import { generateSEOTags } from "spa-prerender-static";// Generate custom SEO tags
const customTags = generateSEOTags({
title: "Product Page",
description: "Check out our amazing product",
url: "https://example.com/product",
image: "https://example.com/product-image.jpg",
keywords: "product, ecommerce, shopping",
robots: "index, follow",
schema: {
"@context": "https://schema.org",
"@type": "Product",
name: "Amazing Product",
offers: {
"@type": "Offer",
price: "29.99",
priceCurrency: "USD",
},
},
});
console.log(customTags);
`Integration with Build Tools
$3
`typescript
// vite.config.ts
import { defineConfig } from "vite";
import { prerender } from "spa-prerender-static";export default defineConfig({
build: {
rollupOptions: {
plugins: [
{
name: "prerender",
generateBundle() {
prerender({
routes: [
{ path: "/", tags: { title: "Home", description: "Welcome" } },
],
template: "./dist/index.html",
dist: "./dist",
render: (route) => '
',
});
},
},
],
},
},
});
`$3
`typescript
// scripts/prerender.js
import { prerender } from "spa-prerender-static";const routes = [
{ path: "/", tags: { title: "Home", description: "Welcome" } },
{ path: "/about", tags: { title: "About", description: "About us" } },
];
prerender({
routes,
template: "./out/index.html",
dist: "./out",
render: async (route) => {
// Your Next.js page rendering logic
return
;
},
});
``MIT © Rahul Sharma
Contributions are welcome! Please feel free to submit a Pull Request.