
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
spa-prerender-static
Advanced tools
A lightweight, framework-agnostic SPA prerendering library for generating SEO-friendly static HTML pages.
A 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.
npm install spa-prerender-static
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 `<div id="app">Content for ${route.path}</div>`;
},
});
prerender(options)Main function to prerender your SPA routes.
Parameters:
options (PrerenderOptions): Configuration object
routes (RouteConfig[]): Array of routes to prerendertemplate (string): Path to HTML template filedist (string): Output directory for static filesrender (function): Function that renders route contentExample:
prerender({
routes: [{ path: "/", tags: { title: "Home", description: "Welcome" } }],
template: "./public/template.html",
dist: "./build",
render: (route) => `<div>App content for ${route.path}</div>`,
});
generateSEOTags(options)Generate SEO meta tags from configuration.
Parameters:
options (SEOTagOptions): SEO configurationReturns:
string: HTML meta tagsExample:
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",
},
});
SEOTagOptionsinterface SEOTagOptions {
title: string;
description: string;
author?: string;
url?: string;
image?: string;
keywords?: string;
canonical?: string;
robots?: string;
ampUrl?: string;
schema?: Record<string, unknown>;
}
RouteConfiginterface RouteConfig {
path: string;
tags: string | SEOTagOptions;
}
PrerenderOptionsinterface PrerenderOptions {
routes: RouteConfig[];
template: string;
dist: string;
render: (route: RouteConfig) => string;
}
Create an HTML template with placeholders that will be replaced during prerendering:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
%TITLE% %LINKS%
</head>
<body>
<div id="app">%APP%</div>
</body>
</html>
Placeholders:
%TITLE% - Page title%APP% - Rendered app content%LINKS% - SEO meta tagsimport { 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 `<div class="page">${content}</div>`;
},
});
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) => `<article>Blog post content here...</article>`,
});
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);
// 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) => '<div id="app"></div>',
});
},
},
],
},
},
});
// 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 `<div>Static content for ${route.path}</div>`;
},
});
MIT © Rahul Sharma
Contributions are welcome! Please feel free to submit a Pull Request.
FAQs
A lightweight, framework-agnostic SPA prerendering library for generating SEO-friendly static HTML pages.
The npm package spa-prerender-static receives a total of 274 weekly downloads. As such, spa-prerender-static popularity was classified as not popular.
We found that spa-prerender-static demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.