@praxisjs/ssg
Changelog for @praxisjs/ssg — static site generation and client-side hydration.
@praxisjs/ssg
0.1.5
Depends on the other @praxisjs/* packages through caret ranges (^2.3.0) instead of exact versions, so npm no longer installs a second copy of a package when two releases disagree, and upgrades no longer end in peer conflicts.
0.1.3
Hydration code only where it is used. render() from @praxisjs/runtime hydrates only once enableHydration() has run, which keeps the reconciliation code out of apps that don't prerender. ssgPlugin() adds that call in front of the client entry (a module script Vite bundles with it), so prerendered pages hydrate exactly as before. With hydrate: false nothing is added. See Enabling hydration.
The published package no longer contains the package's tests (compiled tests in dist/__tests__, test sources in src/__tests__).
Faster prerendering. prerender() used to parse a new JSDOM window for every route, which cost more than rendering most pages. One window now serves the whole run and is reset before each route: a fresh copy of the built index.html, the route's URL, empty storage and none of the window globals the previous route added. 300 routes went from about 900 ms to about 170 ms. Pages are also written to disk in parallel. See Route isolation.
Bug fixes:
localStorageandsessionStorageduring a prerender were the host environment's own, not the page's, so values written by@Persistedon one route showed up on the next. They now belong to the page and start empty for every route.- The JSDOM windows were never closed, so a timer a page started kept running after the build finished with it. The window is now closed at the end of the run.
- A page is now unmounted even when serializing it throws.
- An absolute
build.outDirinvite.config.tswas joined onto the project root instead of being used as is, so the plugin read and wrote under the wrong directory.
0.1.0
Initial release.
ssgPlugin({ root, routerOptions?, hydrate? }) plugs into vite.config.ts alongside praxisjs(). root exports the app's root component (default export) and route table (named routes). A dynamic route like /blog/:slug expands into concrete paths via its own getStaticPaths: (fullPath) => Promise<string[]> declared directly on the route object — colocated, no path matching needed, and the route's own full path is passed in for helpers like @praxisjs/content's collectionStaticPaths() — with a top-level getStaticPaths named export on root available as a fallback for routes that don't declare their own. After vite build, it prerenders every route into its own index.html, waiting for resource()/@Collection data — and any Lazy(...)-wrapped route/layout component — to settle before serializing. The lower-level prerender() function does the same work without the Vite integration, for custom build pipelines.
By default the output is marked for client-side hydration (@praxisjs/runtime's render() reconciles the real DOM instead of discarding it); pass hydrate: false to fall back to a plain client remount instead.