Skip to main content

Prerender API

The CLI covers the common case. When you need to drive rendering from your own build script – a different template per page, a computed output path, content fetched before the render – import prerender directly.

import { prerender } from "nodality/ssg";

await prerender({
template: "src/index.html",
output: "upload/index.html",
build: async () => {
const elements = [{ type: "h1", text: "Hello" }];
const nodes = [{ op: "blast" }];

new Des()
.nodes(nodes)
.add(elements)
.set({ mount: "#mount" });
}
});

template, output and build are required; build must be an async function. The rest have defaults.

Options​

OptionDefaultMeaning
template–HTML shell to render into. Required
output–Where to write the result. Required
build–Async function that constructs the page. Required
mount"#mount"Selector the rendered tree replaces
url"http://localhost/"Document URL seen by the page
viewport{ width: 390, height: 844 }Size reported to responsive code
locale–Locale for this render
localStorageKey"h7lang"Key the page reads its locale from
htmlLang–lang attribute on <html>
canonical–Canonical URL for this page
alternates–hreflang alternates

viewport matters more than it looks. Responsive code branches on width at build time, so a page prerendered at the default 390px ships its mobile layout as the pre-JavaScript HTML. Set it to match the layout you want crawlers and the first paint to see.

Multiple locales​

prerenderEachLocale renders the same page once per locale, with the locale set before build runs.

import { prerenderEachLocale } from "nodality/ssg";

Whole sites​

prerenderSite takes one config and renders every page, in every locale, and writes a sitemap.

import { prerenderSite } from "nodality/ssg-site";

await prerenderSite({
origin: "https://example.com",
uploadDir: "upload",
pages: [
{ html: "index.html", entry: "pages/index.js" },
{ html: "about.html", entry: "pages/about.js" }
],
locales: ["en", "cs"],
defaultLocale: "en"
});

origin, uploadDir and pages are required, and every page needs both html and entry. Omit locales and it renders a single unlocalised pass.

Each locale runs in its own subprocess. That is deliberate: a page's module-level state – a cached translation table, a memoised layout – would otherwise leak from one locale's render into the next, and the second language would come out subtly wrong in ways that only show up in production.

Node caveat​

The browser bundle touches window when it is imported, so require("nodality") throws in bare Node. The ssg entry points are built for a build script and install their own DOM; if you want to import the library itself outside a browser, provide a DOM first.