vite-react-ssg 0.8.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,13 @@ Static-site generation for React on Vite.
4
4
 
5
5
  See demo(also document): [docs](https://vite-react-ssg.netlify.app/)
6
6
 
7
+ > [!IMPORTANT]
8
+ > **React Router v7 Notice**
9
+ >
10
+ > React Router v7 now has built-in SSG support. If you are using React Router v7, we recommend using its official SSG capabilities for better official support and integration.
11
+ >
12
+ > `vite-react-ssg` will continue to maintain SSG functionality for React Router v6 users.
13
+
7
14
  **🎈 Support for [`@tanstack/router`](https://tanstack.com/router/latest/docs/framework/react/overview)
8
15
  and [`wouter`](https://github.com/molefrog/wouter) is in progress!**
9
16
 
@@ -229,6 +236,10 @@ export const Component = Docs
229
236
  export const entry = 'src/pages/json.tsx'
230
237
 
231
238
  export async function loader() {
239
+ // This code will avoid `shiki` and `node:fs` being mark as 'modulepreload' and sent to the client.
240
+ if (!import.meta.ssr) {
241
+ return null
242
+ }
232
243
  // The code here will not be executed on the client side, and the modules imported will not be sent to the client.
233
244
  const fs = (await import('node:fs'))
234
245
  const cwd = process.cwd()
@@ -585,7 +596,14 @@ interface ViteReactSSGOptions {
585
596
  */
586
597
  onPageRendered?: (route: string, renderedHTML: string, appCtx: ViteReactSSGContext<true>) => Promise<string | null | undefined> | string | null | undefined
587
598
 
588
- onFinished?: () => Promise<void> | void
599
+ /**
600
+ * A function that is run after generation is complete.
601
+ * It receives the build output directory as a string.
602
+ *
603
+ * You can use this to add, edit, or delete files in the output
604
+ directory that you don't want to manage in React.
605
+ */
606
+ onFinished?: (dir: string) => Promise<void> | void
589
607
  /**
590
608
  * The application's root container `id`.
591
609
  *
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from '../shared/vite-react-ssg.B2xAADcy.mjs';
3
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, d as RouterOptions, S as StyleCollector, b as ViteReactSSGOptions } from '../shared/vite-react-ssg.B2xAADcy.mjs';
2
+ import { V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from '../shared/vite-react-ssg.CHKvDn8n.mjs';
3
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, c as RouterOptions, S as StyleCollector, d as ViteReactSSGOptions } from '../shared/vite-react-ssg.CHKvDn8n.mjs';
4
4
  export { C as ClientOnly, H as Head } from '../shared/vite-react-ssg.-NlgsPvg.mjs';
5
5
  import 'beasties';
6
6
  import 'react-router-dom';
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from '../shared/vite-react-ssg.B2xAADcy.js';
3
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, d as RouterOptions, S as StyleCollector, b as ViteReactSSGOptions } from '../shared/vite-react-ssg.B2xAADcy.js';
2
+ import { V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from '../shared/vite-react-ssg.CHKvDn8n.js';
3
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, c as RouterOptions, S as StyleCollector, d as ViteReactSSGOptions } from '../shared/vite-react-ssg.CHKvDn8n.js';
4
4
  export { C as ClientOnly, H as Head } from '../shared/vite-react-ssg.-NlgsPvg.js';
5
5
  import 'beasties';
6
6
  import 'react-router-dom';
@@ -1,8 +1,8 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { HelmetProvider } from 'react-helmet-async';
3
- import { r as render, h as hydrate, d as documentReady } from '../shared/vite-react-ssg.BxjO14Et.mjs';
4
- export { C as ClientOnly, H as Head } from '../shared/vite-react-ssg.BxjO14Et.mjs';
3
+ import { r as render, h as hydrate, d as documentReady } from '../shared/vite-react-ssg.DTTf7HZy.mjs';
5
4
  import { d as deserializeState } from '../shared/vite-react-ssg.C6pK7rvr.mjs';
5
+ export { C as ClientOnly, H as Head } from '../shared/vite-react-ssg.CoMLbIiW.mjs';
6
6
  import 'react';
7
7
  import 'react-dom';
8
8
 
package/dist/index.d.mts CHANGED
@@ -1,24 +1,40 @@
1
- import { V as ViteReactSSGContext, d as RouterOptions, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.B2xAADcy.mjs';
2
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, S as StyleCollector, b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.mjs';
1
+ import { V as ViteReactSSGContext, c as RouterOptions, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.CHKvDn8n.mjs';
2
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, S as StyleCollector, d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.mjs';
3
3
  export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.-NlgsPvg.mjs';
4
- import { LinkProps, NavLinkProps } from 'react-router-dom';
5
- import React from 'react';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
5
  import 'beasties';
6
+ import 'react';
7
+ import 'react-router-dom';
7
8
  import 'react-helmet-async';
8
9
 
9
10
  /**
10
11
  * @deprecated Please use `Link` from 'react-router-dom' instead.
11
12
  */
12
- declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
13
+ declare function Link({ ref, ...props }: {
14
+ [x: string]: any;
15
+ ref: any;
16
+ }): react_jsx_runtime.JSX.Element;
17
+ declare namespace Link {
18
+ var displayName: string;
19
+ }
13
20
  /**
14
21
  * @deprecated Please use `NavLink` from 'react-router-dom' instead.
15
22
  */
16
- declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefAttributes<HTMLAnchorElement>>;
23
+ declare function NavLink({ ref, ...props }: {
24
+ [x: string]: any;
25
+ ref: any;
26
+ }): react_jsx_runtime.JSX.Element;
27
+ declare namespace NavLink {
28
+ var displayName: string;
29
+ }
17
30
 
18
31
  declare function ViteReactSSG(routerOptions: RouterOptions, fn?: (context: ViteReactSSGContext<true>) => Promise<void> | void, options?: ViteReactSSGClientOptions): (client?: boolean, routePath?: string) => Promise<ViteReactSSGContext<true>>;
19
32
  declare global {
20
33
  interface Window {
21
- __VITE_REACT_SSG_STATIC_LOADER_DATA__: any;
34
+ /** Manifest index: route path -> data file path */
35
+ __VITE_REACT_SSG_STATIC_LOADER_MANIFEST__: Record<string, string>;
36
+ /** Cached loader data: route path -> loader data */
37
+ __VITE_REACT_SSG_STATIC_LOADER_DATA__: Record<string, Record<string, unknown>>;
22
38
  __VITE_REACT_SSG_HASH__: string;
23
39
  __VITE_REACT_SSG_CONTEXT__: ViteReactSSGContext<true>;
24
40
  }
package/dist/index.d.ts CHANGED
@@ -1,24 +1,40 @@
1
- import { V as ViteReactSSGContext, d as RouterOptions, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.B2xAADcy.js';
2
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, S as StyleCollector, b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.js';
1
+ import { V as ViteReactSSGContext, c as RouterOptions, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.CHKvDn8n.js';
2
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, S as StyleCollector, d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.js';
3
3
  export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.-NlgsPvg.js';
4
- import { LinkProps, NavLinkProps } from 'react-router-dom';
5
- import React from 'react';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
5
  import 'beasties';
6
+ import 'react';
7
+ import 'react-router-dom';
7
8
  import 'react-helmet-async';
8
9
 
9
10
  /**
10
11
  * @deprecated Please use `Link` from 'react-router-dom' instead.
11
12
  */
12
- declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
13
+ declare function Link({ ref, ...props }: {
14
+ [x: string]: any;
15
+ ref: any;
16
+ }): react_jsx_runtime.JSX.Element;
17
+ declare namespace Link {
18
+ var displayName: string;
19
+ }
13
20
  /**
14
21
  * @deprecated Please use `NavLink` from 'react-router-dom' instead.
15
22
  */
16
- declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefAttributes<HTMLAnchorElement>>;
23
+ declare function NavLink({ ref, ...props }: {
24
+ [x: string]: any;
25
+ ref: any;
26
+ }): react_jsx_runtime.JSX.Element;
27
+ declare namespace NavLink {
28
+ var displayName: string;
29
+ }
17
30
 
18
31
  declare function ViteReactSSG(routerOptions: RouterOptions, fn?: (context: ViteReactSSGContext<true>) => Promise<void> | void, options?: ViteReactSSGClientOptions): (client?: boolean, routePath?: string) => Promise<ViteReactSSGContext<true>>;
19
32
  declare global {
20
33
  interface Window {
21
- __VITE_REACT_SSG_STATIC_LOADER_DATA__: any;
34
+ /** Manifest index: route path -> data file path */
35
+ __VITE_REACT_SSG_STATIC_LOADER_MANIFEST__: Record<string, string>;
36
+ /** Cached loader data: route path -> loader data */
37
+ __VITE_REACT_SSG_STATIC_LOADER_DATA__: Record<string, Record<string, unknown>>;
22
38
  __VITE_REACT_SSG_HASH__: string;
23
39
  __VITE_REACT_SSG_CONTEXT__: ViteReactSSGContext<true>;
24
40
  }
package/dist/index.mjs CHANGED
@@ -1,15 +1,14 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { HelmetProvider } from 'react-helmet-async';
3
3
  import { useLinkClickHandler, Link as Link$1, NavLink as NavLink$1, matchRoutes, createBrowserRouter, RouterProvider } from 'react-router-dom';
4
- import { r as render, h as hydrate, d as documentReady } from './shared/vite-react-ssg.BxjO14Et.mjs';
5
- export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.BxjO14Et.mjs';
6
- import { j as joinUrlSegments, w as withLeadingSlash, s as stripBase } from './shared/vite-react-ssg.CjIppNIS.mjs';
7
- import { c as convertRoutesToDataRoutes } from './shared/vite-react-ssg.C0y5wbxl.mjs';
4
+ import { r as render, h as hydrate, d as documentReady } from './shared/vite-react-ssg.DTTf7HZy.mjs';
5
+ import { c as convertRoutesToDataRoutes, j as joinUrlSegments, w as withLeadingSlash, s as stripBase } from './shared/vite-react-ssg.BhGKpaqQ.mjs';
8
6
  import { d as deserializeState } from './shared/vite-react-ssg.C6pK7rvr.mjs';
9
- import React, { forwardRef } from 'react';
7
+ export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.CoMLbIiW.mjs';
8
+ import React from 'react';
10
9
  import 'react-dom';
11
10
 
12
- const Link = forwardRef((props, ref) => {
11
+ function Link({ ref, ...props }) {
13
12
  const {
14
13
  replace,
15
14
  state,
@@ -38,9 +37,9 @@ const Link = forwardRef((props, ref) => {
38
37
  event.preventDefault();
39
38
  }
40
39
  return /* @__PURE__ */ jsx(Link$1, { ...props, ref, onClick: handleClick });
41
- });
40
+ }
42
41
  Link.displayName = "Link";
43
- const NavLink = forwardRef((props, ref) => {
42
+ function NavLink({ ref, ...props }) {
44
43
  const {
45
44
  replace,
46
45
  state,
@@ -69,7 +68,7 @@ const NavLink = forwardRef((props, ref) => {
69
68
  event.preventDefault();
70
69
  }
71
70
  return /* @__PURE__ */ jsx(NavLink$1, { ...props, ref, onClick: handleClick });
72
- });
71
+ }
73
72
  NavLink.displayName = "NavLink";
74
73
 
75
74
  function ViteReactSSG(routerOptions, fn, options = {}) {
@@ -79,14 +78,20 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
79
78
  ssrWhenDev,
80
79
  getStyleCollector = null
81
80
  } = options;
82
- if (process.env.NODE_ENV === "development" && ssrWhenDev !== void 0)
83
- console.warn("[vite-react-ssg] `ssrWhenDev` option is no longer needed. If you want to use csr, just replace `vite-react-ssg dev` with `vite`.");
81
+ if (process.env.NODE_ENV === "development" && ssrWhenDev !== void 0) {
82
+ console.warn(
83
+ "[vite-react-ssg] `ssrWhenDev` option is no longer needed. If you want to use csr, just replace `vite-react-ssg dev` with `vite`."
84
+ );
85
+ }
84
86
  const isClient = typeof window !== "undefined";
85
87
  const BASE_URL = routerOptions.basename ?? "/";
86
88
  const { v7_startTransition = true, ...routerFeature } = routerOptions.future ?? {};
87
89
  async function createRoot(client = false, routePath) {
88
90
  const browserRouter = client ? createBrowserRouter(
89
- convertRoutesToDataRoutes(routerOptions.routes, transformStaticLoaderRoute),
91
+ convertRoutesToDataRoutes(
92
+ routerOptions.routes,
93
+ transformStaticLoaderRoute
94
+ ),
90
95
  { basename: BASE_URL, future: routerFeature }
91
96
  ) : void 0;
92
97
  const appRenderCallbacks = [];
@@ -128,9 +133,11 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
128
133
  console.warn("[vite-react-ssg] Root container not found.");
129
134
  return;
130
135
  }
131
- const lazeMatches = matchRoutes(routerOptions.routes, window.location, BASE_URL)?.filter(
132
- (m) => m.route.lazy
133
- );
136
+ const lazeMatches = matchRoutes(
137
+ routerOptions.routes,
138
+ window.location,
139
+ BASE_URL
140
+ )?.filter((m) => m.route.lazy);
134
141
  if (lazeMatches && lazeMatches?.length > 0) {
135
142
  await Promise.all(
136
143
  lazeMatches.map(async (m) => {
@@ -164,20 +171,31 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
164
171
  const url = request.url.includes("?") ? `${request.url}&${dataQuery}` : `${request.url}?${dataQuery}`;
165
172
  return fetch(url);
166
173
  } else {
167
- let staticLoadData;
168
- if (window.__VITE_REACT_SSG_STATIC_LOADER_DATA__) {
169
- staticLoadData = window.__VITE_REACT_SSG_STATIC_LOADER_DATA__;
170
- } else {
171
- const manifestUrl = joinUrlSegments(BASE_URL, `static-loader-data-manifest-${window.__VITE_REACT_SSG_HASH__}.json`);
172
- staticLoadData = await (await fetch(withLeadingSlash(manifestUrl))).json();
173
- window.__VITE_REACT_SSG_STATIC_LOADER_DATA__ = staticLoadData;
174
+ if (!window.__VITE_REACT_SSG_STATIC_LOADER_MANIFEST__) {
175
+ const manifestUrl = joinUrlSegments(
176
+ BASE_URL,
177
+ `static-loader-data-manifest-${window.__VITE_REACT_SSG_HASH__}.json`
178
+ );
179
+ window.__VITE_REACT_SSG_STATIC_LOADER_MANIFEST__ = await (await fetch(withLeadingSlash(manifestUrl))).json();
174
180
  }
175
181
  const { url } = request;
176
182
  let { pathname } = new URL(url);
177
183
  if (BASE_URL !== "/") {
178
184
  pathname = stripBase(pathname, BASE_URL);
179
185
  }
180
- const routeData = staticLoadData?.[pathname]?.[route.id];
186
+ const manifest = window.__VITE_REACT_SSG_STATIC_LOADER_MANIFEST__;
187
+ const dataFilePath = manifest?.[pathname];
188
+ if (!dataFilePath) {
189
+ return null;
190
+ }
191
+ if (!window.__VITE_REACT_SSG_STATIC_LOADER_DATA__) {
192
+ window.__VITE_REACT_SSG_STATIC_LOADER_DATA__ = {};
193
+ }
194
+ if (!window.__VITE_REACT_SSG_STATIC_LOADER_DATA__[pathname]) {
195
+ const dataUrl = joinUrlSegments(BASE_URL, dataFilePath);
196
+ window.__VITE_REACT_SSG_STATIC_LOADER_DATA__[pathname] = await (await fetch(withLeadingSlash(dataUrl))).json();
197
+ }
198
+ const routeData = window.__VITE_REACT_SSG_STATIC_LOADER_DATA__[pathname]?.[route.id];
181
199
  return routeData ?? null;
182
200
  }
183
201
  };
@@ -1,2 +1,2 @@
1
1
 
2
- export { }
2
+ export { };
@@ -1,2 +1,2 @@
1
1
 
2
- export { }
2
+ export { };
package/dist/node/cli.mjs CHANGED
@@ -1,22 +1,21 @@
1
1
  import { gray, bold, red, reset, underline } from 'kolorist';
2
2
  import yargs from 'yargs';
3
3
  import { hideBin } from 'yargs/helpers';
4
- import { b as build, d as dev } from '../shared/vite-react-ssg.qp2k9AZ2.mjs';
4
+ import { b as build, d as dev } from '../shared/vite-react-ssg.DsKK_1op.mjs';
5
5
  import 'node:module';
6
6
  import 'node:path';
7
7
  import 'fs-extra';
8
8
  import 'jsdom';
9
9
  import 'p-queue';
10
10
  import 'vite';
11
- import '../shared/vite-react-ssg.CjIppNIS.mjs';
11
+ import '../shared/vite-react-ssg.BhGKpaqQ.mjs';
12
12
  import '../shared/vite-react-ssg.C6pK7rvr.mjs';
13
13
  import 'react/jsx-runtime';
14
14
  import 'react-helmet-async';
15
15
  import 'node:events';
16
16
  import 'node:stream';
17
- import '../shared/vite-react-ssg.C0y5wbxl.mjs';
18
17
  import 'react-dom/server';
19
- import '../shared/vite-react-ssg.B-j07kW6.mjs';
18
+ import '../shared/vite-react-ssg.BqDzTpJh.mjs';
20
19
 
21
20
  yargs(hideBin(process.argv)).scriptName("vite-react-ssg").usage("$0 [args]").command(
22
21
  "build",
package/dist/node.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.mjs';
2
+ import { d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.mjs';
3
3
  import 'beasties';
4
4
  import 'react';
5
5
  import 'react-router-dom';
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.js';
2
+ import { d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.js';
3
3
  import 'beasties';
4
4
  import 'react';
5
5
  import 'react-router-dom';
package/dist/node.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { b as build, d as dev } from './shared/vite-react-ssg.qp2k9AZ2.mjs';
1
+ export { b as build, d as dev } from './shared/vite-react-ssg.DsKK_1op.mjs';
2
2
  import 'node:module';
3
3
  import 'node:path';
4
4
  import 'fs-extra';
@@ -6,12 +6,11 @@ import 'jsdom';
6
6
  import 'kolorist';
7
7
  import 'p-queue';
8
8
  import 'vite';
9
- import './shared/vite-react-ssg.CjIppNIS.mjs';
9
+ import './shared/vite-react-ssg.BhGKpaqQ.mjs';
10
10
  import './shared/vite-react-ssg.C6pK7rvr.mjs';
11
11
  import 'react/jsx-runtime';
12
12
  import 'react-helmet-async';
13
13
  import 'node:events';
14
14
  import 'node:stream';
15
- import './shared/vite-react-ssg.C0y5wbxl.mjs';
16
15
  import 'react-dom/server';
17
- import './shared/vite-react-ssg.B-j07kW6.mjs';
16
+ import './shared/vite-react-ssg.BqDzTpJh.mjs';
@@ -1,3 +1,32 @@
1
+ function joinUrlSegments(a, b) {
2
+ if (!a || !b)
3
+ return a || b || "";
4
+ if (a[a.length - 1] === "/")
5
+ a = a.substring(0, a.length - 1);
6
+ if (b[0] !== "/")
7
+ b = `/${b}`;
8
+ return a + b;
9
+ }
10
+ function removeLeadingSlash(str) {
11
+ return str[0] === "/" ? str.slice(1) : str;
12
+ }
13
+ function stripBase(path, base) {
14
+ if (path === base)
15
+ return "/";
16
+ const devBase = withTrailingSlash(base);
17
+ return path.startsWith(devBase) ? path.slice(devBase.length - 1) : path;
18
+ }
19
+ function withTrailingSlash(path) {
20
+ if (path[path.length - 1] !== "/")
21
+ return `${path}/`;
22
+ return path;
23
+ }
24
+ function withLeadingSlash(path) {
25
+ if (path[0] !== "/")
26
+ return `/${path}`;
27
+ return path;
28
+ }
29
+
1
30
  function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath = []) {
2
31
  return routes.map((route, index) => {
3
32
  const treePath = [...parentPath, String(index)];
@@ -33,4 +62,4 @@ function isIndexRoute(route) {
33
62
  return route.index === true;
34
63
  }
35
64
 
36
- export { convertRoutesToDataRoutes as c };
65
+ export { withTrailingSlash as a, convertRoutesToDataRoutes as c, joinUrlSegments as j, removeLeadingSlash as r, stripBase as s, withLeadingSlash as w };
@@ -0,0 +1,5 @@
1
+ function registerPaths(id, getStaticPaths) {
2
+ }
3
+ const META_CONTAINER_ID = "__SSG_TANSTACK_META_CONTAINER__";
4
+
5
+ export { META_CONTAINER_ID as M, registerPaths as r };
@@ -121,7 +121,7 @@ interface ViteReactSSGOptions<Context = ViteReactSSGContext> {
121
121
  * The returned value will be used as the HTML of the route.
122
122
  */
123
123
  onPageRendered?: (route: string, renderedHTML: string, appCtx: Context) => Promise<string | null | undefined> | string | null | undefined;
124
- onFinished?: () => Promise<void> | void;
124
+ onFinished?: (dir: string) => Promise<void> | void;
125
125
  /**
126
126
  * The application's root container `id`.
127
127
  *
@@ -216,4 +216,4 @@ declare module 'vite' {
216
216
  }
217
217
  }
218
218
 
219
- export type { CrittersOptions as C, IndexRouteRecord as I, NonIndexRouteRecord as N, RouteRecord as R, StyleCollector as S, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, ViteReactSSGOptions as b, RouterFutureConfig as c, RouterOptions as d };
219
+ export type { CrittersOptions as C, IndexRouteRecord as I, NonIndexRouteRecord as N, RouteRecord as R, StyleCollector as S, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, RouterFutureConfig as b, RouterOptions as c, ViteReactSSGOptions as d };
@@ -121,7 +121,7 @@ interface ViteReactSSGOptions<Context = ViteReactSSGContext> {
121
121
  * The returned value will be used as the HTML of the route.
122
122
  */
123
123
  onPageRendered?: (route: string, renderedHTML: string, appCtx: Context) => Promise<string | null | undefined> | string | null | undefined;
124
- onFinished?: () => Promise<void> | void;
124
+ onFinished?: (dir: string) => Promise<void> | void;
125
125
  /**
126
126
  * The application's root container `id`.
127
127
  *
@@ -216,4 +216,4 @@ declare module 'vite' {
216
216
  }
217
217
  }
218
218
 
219
- export type { CrittersOptions as C, IndexRouteRecord as I, NonIndexRouteRecord as N, RouteRecord as R, StyleCollector as S, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, ViteReactSSGOptions as b, RouterFutureConfig as c, RouterOptions as d };
219
+ export type { CrittersOptions as C, IndexRouteRecord as I, NonIndexRouteRecord as N, RouteRecord as R, StyleCollector as S, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, RouterFutureConfig as b, RouterOptions as c, ViteReactSSGOptions as d };
@@ -0,0 +1,34 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useEffect, isValidElement } from 'react';
3
+ import { Helmet } from 'react-helmet-async';
4
+
5
+ function useIsClient() {
6
+ const [isBrowser, setIsBrowser] = useState(false);
7
+ useEffect(() => {
8
+ setIsBrowser(true);
9
+ }, []);
10
+ return isBrowser;
11
+ }
12
+
13
+ function ClientOnly({
14
+ children,
15
+ fallback
16
+ }) {
17
+ const isBrowser = useIsClient();
18
+ if (isBrowser) {
19
+ if (typeof children !== "function" && process.env.NODE_ENV === "development") {
20
+ throw new Error(
21
+ `vite-react-ssg error: The children of <ClientOnly> must be a "render function", e.g. <ClientOnly>{() => <span>{window.location.href}</span>}</ClientOnly>.
22
+ Current type: ${isValidElement(children) ? "React element" : typeof children}`
23
+ );
24
+ }
25
+ return /* @__PURE__ */ jsx(Fragment, { children: children?.() });
26
+ }
27
+ return fallback ?? null;
28
+ }
29
+
30
+ function Head(props) {
31
+ return /* @__PURE__ */ jsx(Helmet, { ...props });
32
+ }
33
+
34
+ export { ClientOnly as C, Head as H };
@@ -1,7 +1,5 @@
1
- import React, { useState, useEffect, isValidElement } from 'react';
1
+ import React from 'react';
2
2
  import * as ReactDOM from 'react-dom';
3
- import { jsx, Fragment } from 'react/jsx-runtime';
4
- import { Helmet } from 'react-helmet-async';
5
3
 
6
4
  const CopyReactDOM = {
7
5
  ...ReactDOM
@@ -65,33 +63,4 @@ function documentReady(_passThrough) {
65
63
  return Promise.resolve(_passThrough);
66
64
  }
67
65
 
68
- function useIsClient() {
69
- const [isBrowser, setIsBrowser] = useState(false);
70
- useEffect(() => {
71
- setIsBrowser(true);
72
- }, []);
73
- return isBrowser;
74
- }
75
-
76
- function ClientOnly({
77
- children,
78
- fallback
79
- }) {
80
- const isBrowser = useIsClient();
81
- if (isBrowser) {
82
- if (typeof children !== "function" && process.env.NODE_ENV === "development") {
83
- throw new Error(
84
- `vite-react-ssg error: The children of <ClientOnly> must be a "render function", e.g. <ClientOnly>{() => <span>{window.location.href}</span>}</ClientOnly>.
85
- Current type: ${isValidElement(children) ? "React element" : typeof children}`
86
- );
87
- }
88
- return /* @__PURE__ */ jsx(Fragment, { children: children?.() });
89
- }
90
- return fallback ?? null;
91
- }
92
-
93
- function Head(props) {
94
- return /* @__PURE__ */ jsx(Helmet, { ...props });
95
- }
96
-
97
- export { ClientOnly as C, Head as H, documentReady as d, hydrate as h, render as r };
66
+ export { documentReady as d, hydrate as h, render as r };
@@ -5,15 +5,14 @@ import { JSDOM } from 'jsdom';
5
5
  import { gray, yellow, blue, dim, cyan, red, green, reset, bold, bgLightCyan } from 'kolorist';
6
6
  import PQueue from 'p-queue';
7
7
  import { resolveConfig, createLogger, build as build$1, mergeConfig, version as version$1, send, createServer } from 'vite';
8
- import { a as withTrailingSlash, r as removeLeadingSlash, w as withLeadingSlash, s as stripBase, j as joinUrlSegments } from './vite-react-ssg.CjIppNIS.mjs';
8
+ import { a as withTrailingSlash, r as removeLeadingSlash, c as convertRoutesToDataRoutes, w as withLeadingSlash, s as stripBase, j as joinUrlSegments } from './vite-react-ssg.BhGKpaqQ.mjs';
9
9
  import { s as serializeState } from './vite-react-ssg.C6pK7rvr.mjs';
10
10
  import { jsx, Fragment } from 'react/jsx-runtime';
11
11
  import { HelmetProvider } from 'react-helmet-async';
12
12
  import { once } from 'node:events';
13
13
  import { Readable, Writable } from 'node:stream';
14
- import { c as convertRoutesToDataRoutes } from './vite-react-ssg.C0y5wbxl.mjs';
15
14
  import * as ReactDomServer from 'react-dom/server';
16
- import { M as META_CONTAINER_ID } from './vite-react-ssg.B-j07kW6.mjs';
15
+ import { M as META_CONTAINER_ID } from './vite-react-ssg.BqDzTpJh.mjs';
17
16
 
18
17
  const DYNAMIC_IMPORT_REGEX = /import\("([^)]+)"\)/g;
19
18
  async function collectAssets({
@@ -356,7 +355,7 @@ class WritableAsPromise extends Writable {
356
355
  }
357
356
  }
358
357
 
359
- const version = "0.8.9";
358
+ const version = "0.9.0";
360
359
 
361
360
  function buildLog(text, count) {
362
361
  console.log(`
@@ -694,6 +693,10 @@ function getAdapter(context) {
694
693
  }
695
694
 
696
695
  const dotVitedir = Number.parseInt(version$1) >= 5 ? [".vite"] : [];
696
+ function getLoaderDataFilePath(routePath, hash) {
697
+ const normalized = routePath === "/" ? "/index" : routePath.endsWith("/") ? `${routePath}index` : routePath;
698
+ return `static-loader-data${withLeadingSlash(normalized)}.${hash}.json`;
699
+ }
697
700
  function DefaultIncludedRoutes(paths, _routes) {
698
701
  return paths.filter((i) => !i.includes(":") && !i.includes("*"));
699
702
  }
@@ -729,36 +732,41 @@ async function build(ssgOptions = {}, viteConfig = {}) {
729
732
  const clientLogger = createLogger();
730
733
  const loggerWarn = clientLogger.warn;
731
734
  clientLogger.warn = (msg, options) => {
732
- if (msg.includes("vite:resolve") && msg.includes("externalized for browser compatibility"))
735
+ if (msg.includes("vite:resolve") && msg.includes("externalized for browser compatibility")) {
733
736
  return;
737
+ }
734
738
  loggerWarn(msg, options);
735
739
  };
736
740
  buildLog("Build for client...");
737
- await build$1(mergeConfig(viteConfig, {
738
- build: {
739
- manifest: true,
740
- ssrManifest: true,
741
- rollupOptions: {
742
- input: {
743
- app: join(root, htmlEntry || "./index.html")
744
- },
745
- // @ts-expect-error rollup type
746
- onLog(level, log, handler) {
747
- if (log.message.includes("react-helmet-async"))
748
- return;
749
- handler(level, log);
741
+ await build$1(
742
+ mergeConfig(viteConfig, {
743
+ build: {
744
+ manifest: true,
745
+ ssrManifest: true,
746
+ rollupOptions: {
747
+ input: {
748
+ app: join(root, htmlEntry || "./index.html")
749
+ },
750
+ // @ts-expect-error rollup type
751
+ onLog(level, log, handler) {
752
+ if (log.message.includes("react-helmet-async"))
753
+ return;
754
+ handler(level, log);
755
+ }
750
756
  }
751
- }
752
- },
753
- customLogger: clientLogger,
754
- mode: config.mode,
755
- plugins: [{
756
- name: "vite-react-ssg:get-oup-dir",
757
- configResolved(resolvedConfig) {
758
- outDir = resolvedConfig.build.outDir || "dist";
759
- }
760
- }]
761
- }));
757
+ },
758
+ customLogger: clientLogger,
759
+ mode: config.mode,
760
+ plugins: [
761
+ {
762
+ name: "vite-react-ssg:get-oup-dir",
763
+ configResolved(resolvedConfig) {
764
+ outDir = resolvedConfig.build.outDir || "dist";
765
+ }
766
+ }
767
+ ]
768
+ })
769
+ );
762
770
  let unmock = () => {
763
771
  };
764
772
  if (mock) {
@@ -768,37 +776,44 @@ async function build(ssgOptions = {}, viteConfig = {}) {
768
776
  buildLog("Build for server...");
769
777
  process.env.VITE_SSG = "true";
770
778
  const ssrEntry = await resolveAlias(config, entry);
771
- await build$1(mergeConfig(viteConfig, {
772
- build: {
773
- ssr: ssrEntry,
774
- manifest: true,
775
- outDir: ssgOut,
776
- minify: false,
777
- cssCodeSplit: false,
778
- rollupOptions: {
779
- output: format === "esm" ? {
780
- entryFileNames: "[name].mjs",
781
- format: "esm"
782
- } : {
783
- entryFileNames: "[name].cjs",
784
- format: "cjs"
785
- },
786
- // @ts-expect-error rollup type
787
- onLog(level, log, handler) {
788
- if (log.message.includes("react-helmet-async"))
789
- return;
790
- handler(level, log);
779
+ await build$1(
780
+ mergeConfig(viteConfig, {
781
+ build: {
782
+ ssr: ssrEntry,
783
+ manifest: true,
784
+ outDir: ssgOut,
785
+ minify: false,
786
+ cssCodeSplit: false,
787
+ rollupOptions: {
788
+ output: format === "esm" ? {
789
+ entryFileNames: "[name].mjs",
790
+ format: "esm"
791
+ } : {
792
+ entryFileNames: "[name].cjs",
793
+ format: "cjs"
794
+ },
795
+ // @ts-expect-error rollup type
796
+ onLog(level, log, handler) {
797
+ if (log.message.includes("react-helmet-async"))
798
+ return;
799
+ handler(level, log);
800
+ }
791
801
  }
792
- }
793
- },
794
- mode: config.mode
795
- }));
802
+ },
803
+ mode: config.mode
804
+ })
805
+ );
796
806
  const prefix = format === "esm" && process.platform === "win32" ? "file://" : "";
797
807
  const ext = format === "esm" ? ".mjs" : ".cjs";
798
808
  const serverEntry = prefix + join(ssgOut, parse(ssrEntry).name + ext).replace(/\\/g, "/");
799
- const serverManifest = JSON.parse(await fs.readFile(join(ssgOut, ...dotVitedir, "manifest.json"), "utf-8"));
809
+ const serverManifest = JSON.parse(
810
+ await fs.readFile(join(ssgOut, ...dotVitedir, "manifest.json"), "utf-8")
811
+ );
800
812
  const _require = createRequire(import.meta.url);
801
- const { createRoot, includedRoutes: serverEntryIncludedRoutes } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
813
+ const {
814
+ createRoot,
815
+ includedRoutes: serverEntryIncludedRoutes
816
+ } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
802
817
  const includedRoutes = serverEntryIncludedRoutes || configIncludedRoutes;
803
818
  const { routes } = await createRoot(false);
804
819
  const { paths } = await routesToPaths(routes);
@@ -806,29 +821,74 @@ async function build(ssgOptions = {}, viteConfig = {}) {
806
821
  routesPaths = DefaultIncludedRoutes(routesPaths);
807
822
  routesPaths = Array.from(new Set(routesPaths));
808
823
  buildLog("Rendering Pages...", routesPaths.length);
809
- const beasties = beastiesOptions !== false ? await getBeastiesOrCritters(outDir, { publicPath: configBase, ...beastiesOptions }) : void 0;
810
- if (beasties)
811
- console.log(`${gray("[vite-react-ssg]")} ${blue("Critical CSS generation enabled via `beasties`")}`);
824
+ const beasties = beastiesOptions !== false ? await getBeastiesOrCritters(outDir, {
825
+ publicPath: configBase,
826
+ ...beastiesOptions
827
+ }) : void 0;
828
+ if (beasties) {
829
+ console.log(
830
+ `${gray("[vite-react-ssg]")} ${blue("Critical CSS generation enabled via `beasties`")}`
831
+ );
832
+ }
812
833
  const out = isAbsolute(outDir) ? outDir : join(root, outDir);
813
- const ssrManifest = JSON.parse(await fs.readFile(join(out, ...dotVitedir, "ssr-manifest.json"), "utf-8"));
814
- const manifest = JSON.parse(await fs.readFile(join(out, ...dotVitedir, "manifest.json"), "utf-8"));
834
+ const ssrManifest = JSON.parse(
835
+ await fs.readFile(join(out, ...dotVitedir, "ssr-manifest.json"), "utf-8")
836
+ );
837
+ const manifest = JSON.parse(
838
+ await fs.readFile(join(out, ...dotVitedir, "manifest.json"), "utf-8")
839
+ );
815
840
  let indexHTML = await fs.readFile(join(out, htmlEntry), "utf-8");
816
841
  fs.rmSync(join(out, htmlEntry));
817
842
  indexHTML = rewriteScripts(indexHTML, script);
818
843
  const queue = new PQueue({ concurrency });
819
844
  const crittersQueue = new PQueue({ concurrency: 1 });
820
845
  const staticLoaderDataManifest = {};
846
+ let loaderDataFileCount = 0;
821
847
  for (const path of routesPaths) {
822
848
  queue.add(async () => {
823
849
  try {
824
- const appCtx = await createRoot(false, path);
825
- const { base, routes: routes2, triggerOnSSRAppRendered, transformState = serializeState, app, routerType } = appCtx;
850
+ const appCtx = await createRoot(
851
+ false,
852
+ path
853
+ );
854
+ const {
855
+ base,
856
+ routes: routes2,
857
+ triggerOnSSRAppRendered,
858
+ transformState = serializeState,
859
+ app,
860
+ routerType
861
+ } = appCtx;
826
862
  const transformedIndexHTML = await onBeforePageRender?.(path, indexHTML, appCtx) || indexHTML;
827
863
  const fetchUrl = `${withTrailingSlash(base)}${removeLeadingSlash(path)}`;
828
864
  const adapter = getAdapter(appCtx);
829
- const assets = !app && routerType === "remix" ? await collectAssets({ routes: [...routes2], locationArg: fetchUrl, base, serverManifest, manifest, ssrManifest }) : /* @__PURE__ */ new Set();
830
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await adapter.render(path);
831
- staticLoaderDataManifest[withLeadingSlash(path)] = routerContext?.loaderData;
865
+ const assets = !app && routerType === "remix" ? await collectAssets({
866
+ routes: [...routes2],
867
+ locationArg: fetchUrl,
868
+ base,
869
+ serverManifest,
870
+ manifest,
871
+ ssrManifest
872
+ }) : /* @__PURE__ */ new Set();
873
+ const {
874
+ appHTML,
875
+ bodyAttributes,
876
+ htmlAttributes,
877
+ metaAttributes,
878
+ styleTag,
879
+ routerContext
880
+ } = await adapter.render(path);
881
+ const loaderData = routerContext?.loaderData;
882
+ if (loaderData && Object.keys(loaderData).length > 0) {
883
+ const loaderDataFilePath = getLoaderDataFilePath(path, hash);
884
+ await fs.ensureDir(join(out, dirname(loaderDataFilePath)));
885
+ await fs.writeFile(
886
+ join(out, loaderDataFilePath),
887
+ JSON.stringify(loaderData)
888
+ );
889
+ staticLoaderDataManifest[withLeadingSlash(path)] = loaderDataFilePath;
890
+ loaderDataFileCount++;
891
+ }
832
892
  await triggerOnSSRAppRendered?.(path, appHTML, appCtx);
833
893
  const renderedHTML = await renderHTML({
834
894
  rootContainerId,
@@ -843,10 +903,18 @@ async function build(ssgOptions = {}, viteConfig = {}) {
843
903
  renderPreloadLinks(jsdom.window.document, assets);
844
904
  const html = jsdom.serialize();
845
905
  let transformed = await onPageRendered?.(path, html, appCtx) || html;
846
- transformed = transformed.replace(SCRIPT_COMMENT_PLACEHOLDER, `window.__VITE_REACT_SSG_HASH__ = '${hash}'`);
906
+ transformed = transformed.replace(
907
+ SCRIPT_COMMENT_PLACEHOLDER,
908
+ `window.__VITE_REACT_SSG_HASH__ = '${hash}'`
909
+ );
847
910
  if (beasties) {
848
- transformed = await crittersQueue.add(() => beasties.process(transformed));
849
- transformed = transformed.replace(/<link\srel="stylesheet"/g, '<link rel="stylesheet" crossorigin');
911
+ transformed = await crittersQueue.add(
912
+ () => beasties.process(transformed)
913
+ );
914
+ transformed = transformed.replace(
915
+ /<link\srel="stylesheet"/g,
916
+ '<link rel="stylesheet" crossorigin'
917
+ );
850
918
  }
851
919
  if (styleTag)
852
920
  transformed = transformed.replace("<head>", `<head>${styleTag}`);
@@ -859,15 +927,24 @@ async function build(ssgOptions = {}, viteConfig = {}) {
859
927
  `${dim(`${outDir}/`)}${cyan(filename.padEnd(15, " "))} ${dim(getSize(formatted))}`
860
928
  );
861
929
  } catch (err) {
862
- throw new Error(`${gray("[vite-react-ssg]")} ${red(`Error on page: ${cyan(path)}`)}
863
- ${err.stack}`);
930
+ throw new Error(
931
+ `${gray("[vite-react-ssg]")} ${red(`Error on page: ${cyan(path)}`)}
932
+ ${err.stack}`
933
+ );
864
934
  }
865
935
  });
866
936
  }
867
937
  await queue.start().onIdle();
868
- buildLog("Generating static loader data manifest...");
869
- const staticLoaderDataManifestString = JSON.stringify(staticLoaderDataManifest, null, 0);
870
- await fs.writeFile(join(out, `static-loader-data-manifest-${hash}.json`), staticLoaderDataManifestString);
938
+ buildLog("Generating static loader data...", loaderDataFileCount);
939
+ const staticLoaderDataManifestString = JSON.stringify(
940
+ staticLoaderDataManifest,
941
+ null,
942
+ 0
943
+ );
944
+ await fs.writeFile(
945
+ join(out, `static-loader-data-manifest-${hash}.json`),
946
+ staticLoaderDataManifestString
947
+ );
871
948
  config.logger.info(
872
949
  `${dim(`${outDir}/`)}${cyan(`static-loader-data-manifest-${hash}.json`.padEnd(15, " "))} ${dim(getSize(staticLoaderDataManifestString))}`
873
950
  );
@@ -880,10 +957,12 @@ ${err.stack}`);
880
957
  }
881
958
  console.log(`
882
959
  ${gray("[vite-react-ssg]")} ${green("Build finished.")}`);
883
- await onFinished?.();
960
+ await onFinished?.(outDir);
884
961
  const waitInSeconds = 15;
885
962
  const timeout = setTimeout(() => {
886
- console.log(`${gray("[vite-react-ssg]")} ${yellow(`Build process still running after ${waitInSeconds}s`)}. There might be something misconfigured in your setup. Force exit.`);
963
+ console.log(
964
+ `${gray("[vite-react-ssg]")} ${yellow(`Build process still running after ${waitInSeconds}s`)}. There might be something misconfigured in your setup. Force exit.`
965
+ );
887
966
  process.exit(0);
888
967
  }, waitInSeconds * 1e3);
889
968
  timeout.unref();
@@ -891,16 +970,25 @@ ${gray("[vite-react-ssg]")} ${green("Build finished.")}`);
891
970
  function rewriteScripts(indexHTML, mode) {
892
971
  if (!mode || mode === "sync")
893
972
  return indexHTML;
894
- return indexHTML.replace(/<script type="module" /g, `<script type="module" ${mode} `);
973
+ return indexHTML.replace(
974
+ /<script type="module" /g,
975
+ `<script type="module" ${mode} `
976
+ );
895
977
  }
896
978
  async function formatHtml(html, formatting) {
897
979
  if (formatting === "prettify") {
898
980
  try {
899
981
  const prettier = (await import('prettier/esm/standalone.mjs')).default;
900
982
  const parserHTML = (await import('prettier/esm/parser-html.mjs')).default;
901
- return prettier.format(html, { semi: false, parser: "html", plugins: [parserHTML] });
983
+ return prettier.format(html, {
984
+ semi: false,
985
+ parser: "html",
986
+ plugins: [parserHTML]
987
+ });
902
988
  } catch (e) {
903
- console.error(`${gray("[vite-react-ssg]")} ${red(`Error formatting html: ${e?.message}`)}`);
989
+ console.error(
990
+ `${gray("[vite-react-ssg]")} ${red(`Error formatting html: ${e?.message}`)}`
991
+ );
904
992
  return html;
905
993
  }
906
994
  }
@@ -1,6 +1,6 @@
1
1
  import { AnyRouter } from '@tanstack/react-router';
2
- import { V as ViteReactSSGContext$1, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.B2xAADcy.mjs';
3
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, S as StyleCollector, b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.mjs';
2
+ import { V as ViteReactSSGContext$1, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.CHKvDn8n.mjs';
3
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, S as StyleCollector, d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.mjs';
4
4
  export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.-NlgsPvg.mjs';
5
5
  import 'beasties';
6
6
  import 'react';
@@ -22,10 +22,14 @@ type ViteReactSSGContext<HasRouter extends boolean = true> = Omit<ViteReactSSGCo
22
22
  declare function Experimental_ViteReactSSG(routerOptions: RouterOptions, fn?: (context: ViteReactSSGContext<true>) => Promise<void> | void, options?: ViteReactSSGClientOptions): (client?: boolean, routePath?: string) => Promise<ViteReactSSGContext<true>>;
23
23
  declare global {
24
24
  interface Window {
25
- __VITE_REACT_SSG_STATIC_LOADER_DATA__: any;
25
+ /** Manifest index: route path -> data file path */
26
+ __VITE_REACT_SSG_STATIC_LOADER_MANIFEST__: Record<string, string>;
27
+ /** Cached loader data: route path -> loader data */
28
+ __VITE_REACT_SSG_STATIC_LOADER_DATA__: Record<string, Record<string, unknown>>;
26
29
  __VITE_REACT_SSG_HASH__: string;
27
30
  __VITE_REACT_SSG_CONTEXT__: ViteReactSSGContext<true>;
28
31
  }
29
32
  }
30
33
 
31
- export { Experimental_ViteReactSSG, type RouterOptions, ViteReactSSGClientOptions, type ViteReactSSGContext, registerPaths };
34
+ export { Experimental_ViteReactSSG, ViteReactSSGClientOptions, registerPaths };
35
+ export type { RouterOptions, ViteReactSSGContext };
@@ -1,6 +1,6 @@
1
1
  import { AnyRouter } from '@tanstack/react-router';
2
- import { V as ViteReactSSGContext$1, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.B2xAADcy.js';
3
- export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, c as RouterFutureConfig, S as StyleCollector, b as ViteReactSSGOptions } from './shared/vite-react-ssg.B2xAADcy.js';
2
+ import { V as ViteReactSSGContext$1, a as ViteReactSSGClientOptions } from './shared/vite-react-ssg.CHKvDn8n.js';
3
+ export { C as CrittersOptions, I as IndexRouteRecord, N as NonIndexRouteRecord, R as RouteRecord, b as RouterFutureConfig, S as StyleCollector, d as ViteReactSSGOptions } from './shared/vite-react-ssg.CHKvDn8n.js';
4
4
  export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.-NlgsPvg.js';
5
5
  import 'beasties';
6
6
  import 'react';
@@ -22,10 +22,14 @@ type ViteReactSSGContext<HasRouter extends boolean = true> = Omit<ViteReactSSGCo
22
22
  declare function Experimental_ViteReactSSG(routerOptions: RouterOptions, fn?: (context: ViteReactSSGContext<true>) => Promise<void> | void, options?: ViteReactSSGClientOptions): (client?: boolean, routePath?: string) => Promise<ViteReactSSGContext<true>>;
23
23
  declare global {
24
24
  interface Window {
25
- __VITE_REACT_SSG_STATIC_LOADER_DATA__: any;
25
+ /** Manifest index: route path -> data file path */
26
+ __VITE_REACT_SSG_STATIC_LOADER_MANIFEST__: Record<string, string>;
27
+ /** Cached loader data: route path -> loader data */
28
+ __VITE_REACT_SSG_STATIC_LOADER_DATA__: Record<string, Record<string, unknown>>;
26
29
  __VITE_REACT_SSG_HASH__: string;
27
30
  __VITE_REACT_SSG_CONTEXT__: ViteReactSSGContext<true>;
28
31
  }
29
32
  }
30
33
 
31
- export { Experimental_ViteReactSSG, type RouterOptions, ViteReactSSGClientOptions, type ViteReactSSGContext, registerPaths };
34
+ export { Experimental_ViteReactSSG, ViteReactSSGClientOptions, registerPaths };
35
+ export type { RouterOptions, ViteReactSSGContext };
package/dist/tanstack.mjs CHANGED
@@ -1,143 +1,15 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { RouterProvider } from '@tanstack/react-router';
3
- import { Meta, StartClient } from '@tanstack/start';
4
- import { HelmetProvider } from 'react-helmet-async';
5
- import { r as render, h as hydrate, d as documentReady } from './shared/vite-react-ssg.BxjO14Et.mjs';
6
- export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.BxjO14Et.mjs';
7
- import { j as joinUrlSegments, w as withLeadingSlash, s as stripBase } from './shared/vite-react-ssg.CjIppNIS.mjs';
8
- import { d as deserializeState } from './shared/vite-react-ssg.C6pK7rvr.mjs';
9
- import { M as META_CONTAINER_ID, c as convertRouteTreeToRouteOption } from './shared/vite-react-ssg.B-j07kW6.mjs';
10
- export { r as registerPaths } from './shared/vite-react-ssg.B-j07kW6.mjs';
1
+ import 'react/jsx-runtime';
2
+ import '@tanstack/react-router';
3
+ import '@tanstack/start';
4
+ import 'react-helmet-async';
5
+ export { r as registerPaths } from './shared/vite-react-ssg.BqDzTpJh.mjs';
6
+ export { C as ClientOnly, H as Head } from './shared/vite-react-ssg.CoMLbIiW.mjs';
11
7
  import 'react';
12
- import 'react-dom';
13
8
 
14
- const HAS_ADD_META_FLAG_KEY = "HAS_ADD_META_FLAG_KEY";
15
9
  function Experimental_ViteReactSSG(routerOptions, fn, options = {}) {
16
- const {
17
- transformState,
18
- rootContainer = "#root",
19
- ssrWhenDev,
20
- getStyleCollector = null
21
- } = options;
22
- if (process.env.NODE_ENV === "development" && ssrWhenDev !== void 0)
23
- console.warn("[vite-react-ssg] `ssrWhenDev` option is no longer needed. If you want to use csr, just replace `vite-react-ssg dev` with `vite`.");
24
- const isClient = typeof window !== "undefined";
25
- const BASE_URL = routerOptions.basename ?? "/";
26
- const routeTree = routerOptions.routes;
27
- const OriginComponent = routeTree.options.component;
28
- if (!OriginComponent[HAS_ADD_META_FLAG_KEY]) {
29
- const component = () => /* @__PURE__ */ jsxs(Fragment, { children: [
30
- /* @__PURE__ */ jsx(OriginComponent, {}),
31
- /* @__PURE__ */ jsx("div", { id: META_CONTAINER_ID, style: { display: "none" }, children: /* @__PURE__ */ jsx(Meta, {}) })
32
- ] });
33
- component[HAS_ADD_META_FLAG_KEY] = true;
34
- routeTree.update({
35
- component
36
- });
37
- }
38
- async function createRoot(client = false, routePath) {
39
- const routes = await convertRouteTreeToRouteOption(
40
- routerOptions.routes,
41
- client,
42
- client ? (node) => {
43
- const isSSR = document.querySelector("[data-server-rendered=true]") !== null;
44
- if (!isSSR)
45
- return;
46
- node.options.loader = async (ctx) => {
47
- let pathname = ctx.location.pathname;
48
- if (process.env.NODE_ENV === "development") {
49
- const routeId = encodeURIComponent(node.id);
50
- const dataQuery = `_data=${routeId}`;
51
- const href = ctx.location.href;
52
- const url = href.includes("?") ? `${href}&${dataQuery}` : `${href}?${dataQuery}`;
53
- const res = await fetch(url);
54
- const header = res.headers;
55
- const contentType = header.get("content-type");
56
- if (contentType?.startsWith("application/json"))
57
- return res.json();
58
- return res.text();
59
- }
60
- let staticLoadData;
61
- if (window.__VITE_REACT_SSG_STATIC_LOADER_DATA__) {
62
- staticLoadData = window.__VITE_REACT_SSG_STATIC_LOADER_DATA__;
63
- } else {
64
- const manifestUrl = joinUrlSegments(BASE_URL, `static-loader-data-manifest-${window.__VITE_REACT_SSG_HASH__}.json`);
65
- staticLoadData = await (await fetch(withLeadingSlash(manifestUrl))).json();
66
- window.__VITE_REACT_SSG_STATIC_LOADER_DATA__ = staticLoadData;
67
- }
68
- if (BASE_URL !== "/") {
69
- pathname = stripBase(pathname, BASE_URL);
70
- }
71
- const routeData = staticLoadData?.[pathname]?.find((item) => item.id === node.id);
72
- return routeData?.loaderData ?? null;
73
- };
74
- } : void 0
75
- );
76
- const router = routerOptions.router;
77
- router.options.isServer = !client;
78
- const appRenderCallbacks = [];
79
- const onSSRAppRendered = client ? () => {
80
- } : (cb) => appRenderCallbacks.push(cb);
81
- const triggerOnSSRAppRendered = () => {
82
- return Promise.all(appRenderCallbacks.map((cb) => cb()));
83
- };
84
- const context = {
85
- isClient,
86
- routes,
87
- routeTree,
88
- router,
89
- routerOptions: {
90
- routes,
91
- basename: BASE_URL
92
- },
93
- onSSRAppRendered,
94
- triggerOnSSRAppRendered,
95
- initialState: {},
96
- transformState,
97
- routePath,
98
- base: BASE_URL,
99
- getStyleCollector,
100
- routerType: "tanstack"
101
- };
102
- if (client) {
103
- await documentReady();
104
- context.initialState = transformState?.(window.__INITIAL_STATE__ || {}) || deserializeState(window.__INITIAL_STATE__);
105
- }
106
- await fn?.(context);
107
- const initialState = context.initialState;
108
- return {
109
- ...context,
110
- initialState
111
- };
112
- }
113
- if (isClient) {
114
- (async () => {
115
- const container = typeof rootContainer === "string" ? document.querySelector(rootContainer) : rootContainer;
116
- if (!container) {
117
- if (typeof $jsdom === "undefined")
118
- console.warn("[vite-react-ssg] Root container not found.");
119
- return;
120
- }
121
- const context = await createRoot(true);
122
- window.__VITE_REACT_SSG_CONTEXT__ = context;
123
- const { router } = context;
124
- const isSSR = document.querySelector("[data-server-rendered=true]") !== null;
125
- if (!isSSR && process.env.NODE_ENV === "development") {
126
- render(
127
- /* @__PURE__ */ jsx(HelmetProvider, { children: /* @__PURE__ */ jsx(RouterProvider, { router }) }),
128
- container,
129
- options
130
- );
131
- } else {
132
- hydrate(
133
- /* @__PURE__ */ jsx(HelmetProvider, { children: /* @__PURE__ */ jsx(StartClient, { router }) }),
134
- container,
135
- options
136
- );
137
- }
138
- })();
139
- }
140
- return createRoot;
10
+ throw new Error(
11
+ "[vite-react-ssg] Sorry, this Version has no support for tanstack router. Please contact me via GitHub issue if you need this feature."
12
+ );
141
13
  }
142
14
 
143
15
  export { Experimental_ViteReactSSG };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "vite-react-ssg",
3
3
  "type": "module",
4
- "version": "0.8.9",
5
- "packageManager": "pnpm@10.12.1",
4
+ "version": "0.9.0",
5
+ "packageManager": "pnpm@10.28.2",
6
6
  "description": "Static-site generation for React on Vite.",
7
7
  "author": "Riri <Daydreamerriri@outlook.com>",
8
8
  "license": "MIT",
@@ -69,7 +69,7 @@
69
69
  "build": "unbuild",
70
70
  "dev": "unbuild --stub",
71
71
  "lint": "eslint .",
72
- "test": "pnpm -r --filter=./examples/* build && vitest run",
72
+ "test": "pnpm -r build && vitest run",
73
73
  "prepublishOnly": "nr build",
74
74
  "release": "bumpp && npm publish",
75
75
  "start": "esno src/index.ts",
@@ -109,45 +109,45 @@
109
109
  }
110
110
  },
111
111
  "dependencies": {
112
- "fs-extra": "^11.3.0",
112
+ "fs-extra": "^11.3.3",
113
113
  "html5parser": "^2.0.2",
114
114
  "jsdom": "^24.1.3",
115
115
  "kolorist": "^1.8.0",
116
- "p-queue": "^8.1.0",
116
+ "p-queue": "^9.1.0",
117
117
  "react-helmet-async": "^1.3.0",
118
118
  "yargs": "^17.7.2"
119
119
  },
120
120
  "devDependencies": {
121
- "@ririd/eslint-config": "^1.4.0",
122
- "@tanstack/react-router": "^1.121.24",
121
+ "@ririd/eslint-config": "^2.1.1",
122
+ "@tanstack/react-router": "^1.158.0",
123
123
  "@tanstack/start": "^1.120.20",
124
124
  "@types/fs-extra": "^11.0.4",
125
125
  "@types/jsdom": "^21.1.7",
126
- "@types/node": "^18.19.112",
126
+ "@types/node": "^18.19.130",
127
127
  "@types/react": "catalog:",
128
128
  "@types/react-dom": "catalog:",
129
- "@types/yargs": "^17.0.33",
130
- "@vitejs/plugin-react-swc": "^3.10.2",
131
- "beasties": "^0.3.4",
132
- "bumpp": "^10.2.0",
129
+ "@types/yargs": "^17.0.35",
130
+ "@vitejs/plugin-react-swc": "^3.11.0",
131
+ "beasties": "^0.4.1",
132
+ "bumpp": "^10.4.0",
133
133
  "critters": "^0.0.25",
134
- "eslint": "^9.29.0",
134
+ "eslint": "^9.39.2",
135
135
  "esno": "^4.8.0",
136
136
  "fast-glob": "3.3.2",
137
- "prettier": "^3.5.3",
137
+ "prettier": "^3.8.1",
138
138
  "react": "catalog:",
139
139
  "react-dom": "catalog:",
140
- "react-router-dom": "^6.30.1",
140
+ "react-router-dom": "^6.30.3",
141
141
  "rimraf": "5.0.1",
142
142
  "styled-components": "6.0.5",
143
- "typescript": "^5.8.3",
144
- "unbuild": "^3.5.0",
143
+ "typescript": "^5.9.3",
144
+ "unbuild": "^3.6.1",
145
145
  "vite": "catalog:",
146
146
  "vitest": "1.6.1"
147
147
  },
148
148
  "pnpm": {
149
149
  "overrides": {
150
- "@babel/traverse": "^7.27.4"
150
+ "@babel/traverse": "^7.29.0"
151
151
  },
152
152
  "onlyBuiltDependencies": [
153
153
  "@swc/core",
@@ -1,31 +0,0 @@
1
- const ViteReactSSGTanstackRouterStaticPathsContext = {};
2
- function registerPaths(id, getStaticPaths) {
3
- ViteReactSSGTanstackRouterStaticPathsContext[id] = getStaticPaths;
4
- }
5
- async function convertRouteTreeToRouteOption(routeTree, client, visitNode) {
6
- const routes = [];
7
- async function traverseRouteTree(node) {
8
- if (!client && node.path?.includes("$") && node.lazyFn) {
9
- await node.lazyFn();
10
- }
11
- visitNode?.(node);
12
- const routeRecord = {
13
- path: node.path,
14
- getStaticPaths: ViteReactSSGTanstackRouterStaticPathsContext[node.id]
15
- };
16
- routeRecord.path = routeRecord.path?.replaceAll("$", ":");
17
- const children = node.children;
18
- if (children) {
19
- routeRecord.children = [];
20
- for (const child of Object.values(children)) {
21
- routeRecord.children.push(await traverseRouteTree(child));
22
- }
23
- }
24
- return routeRecord;
25
- }
26
- routes.push(await traverseRouteTree(routeTree));
27
- return routes;
28
- }
29
- const META_CONTAINER_ID = "__SSG_TANSTACK_META_CONTAINER__";
30
-
31
- export { META_CONTAINER_ID as M, convertRouteTreeToRouteOption as c, registerPaths as r };
@@ -1,30 +0,0 @@
1
- function joinUrlSegments(a, b) {
2
- if (!a || !b)
3
- return a || b || "";
4
- if (a[a.length - 1] === "/")
5
- a = a.substring(0, a.length - 1);
6
- if (b[0] !== "/")
7
- b = `/${b}`;
8
- return a + b;
9
- }
10
- function removeLeadingSlash(str) {
11
- return str[0] === "/" ? str.slice(1) : str;
12
- }
13
- function stripBase(path, base) {
14
- if (path === base)
15
- return "/";
16
- const devBase = withTrailingSlash(base);
17
- return path.startsWith(devBase) ? path.slice(devBase.length - 1) : path;
18
- }
19
- function withTrailingSlash(path) {
20
- if (path[path.length - 1] !== "/")
21
- return `${path}/`;
22
- return path;
23
- }
24
- function withLeadingSlash(path) {
25
- if (path[0] !== "/")
26
- return `/${path}`;
27
- return path;
28
- }
29
-
30
- export { withTrailingSlash as a, joinUrlSegments as j, removeLeadingSlash as r, stripBase as s, withLeadingSlash as w };