vite-react-ssg 0.1.0 → 0.1.1

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
@@ -100,7 +100,7 @@ function MyComponent() {
100
100
  }
101
101
  ```
102
102
 
103
- > It's important that the children of <ClientOnly> is not a JSX element, but a function that returns an element.
103
+ > It's important that the children of `<ClientOnly>` is not a JSX element, but a function that returns an element.
104
104
  > Because React will try to render children, and may use the client's API on the server.
105
105
 
106
106
  ## Document head
@@ -170,6 +170,21 @@ export default function MyHead() {
170
170
  }
171
171
  ```
172
172
 
173
+ ## CSS in JS
174
+
175
+ Use the `getStyleCollector` option to specify an SSR/SSG style collector. Currently only supports `styled-components`.
176
+
177
+ ```tsx
178
+ import { ViteReactSSG } from 'vite-react-ssg'
179
+ import { getStyledComponentsCollector } from 'vite-react-ssg/style-collectors'
180
+ import { routes } from './App.js'
181
+ import './index.css'
182
+
183
+ export const createRoot = ViteReactSSG({ routes }, () => {}, { getStyleCollector: getStyledComponentsCollector })
184
+ ```
185
+
186
+ You can provide your own by looking at the [implementation](./src/style-collectors/) of any of the existing collectors.
187
+
173
188
  ## Critical CSS
174
189
 
175
190
  Vite SSG has built-in support for generating [Critical CSS](https://web.dev/extract-critical-css/) inlined in the HTML via the [`critters`](https://github.com/GoogleChromeLabs/critters) package.
package/dist/index.cjs CHANGED
@@ -42,11 +42,73 @@ Current type: ${React.isValidElement(children) ? "React element" : typeof childr
42
42
  return fallback ?? null;
43
43
  }
44
44
 
45
+ const Link = React.forwardRef((props, ref) => {
46
+ const {
47
+ replace,
48
+ state,
49
+ target,
50
+ preventScrollReset,
51
+ relative,
52
+ to,
53
+ onClick
54
+ } = props;
55
+ const internalOnClick = reactRouterDom.useLinkClickHandler(to, {
56
+ replace,
57
+ state,
58
+ target,
59
+ preventScrollReset,
60
+ relative
61
+ });
62
+ function handleClick(event) {
63
+ if (onClick)
64
+ onClick(event);
65
+ if (!event.defaultPrevented) {
66
+ React__default.startTransition(() => {
67
+ internalOnClick(event);
68
+ });
69
+ }
70
+ event.defaultPrevented = true;
71
+ event.preventDefault();
72
+ }
73
+ return /* @__PURE__ */ React__default.createElement(reactRouterDom.Link, { ...props, ref, onClick: handleClick });
74
+ });
75
+ const NavLink = React.forwardRef((props, ref) => {
76
+ const {
77
+ replace,
78
+ state,
79
+ target,
80
+ preventScrollReset,
81
+ relative,
82
+ to,
83
+ onClick
84
+ } = props;
85
+ const internalOnClick = reactRouterDom.useLinkClickHandler(to, {
86
+ replace,
87
+ state,
88
+ target,
89
+ preventScrollReset,
90
+ relative
91
+ });
92
+ function handleClick(event) {
93
+ if (onClick)
94
+ onClick(event);
95
+ if (!event.defaultPrevented) {
96
+ React__default.startTransition(() => {
97
+ internalOnClick(event);
98
+ });
99
+ }
100
+ event.defaultPrevented = true;
101
+ event.preventDefault();
102
+ }
103
+ return /* @__PURE__ */ React__default.createElement(reactRouterDom.NavLink, { ...props, ref, onClick: handleClick });
104
+ });
105
+
45
106
  function ViteReactSSG(routerOptions, fn, options = {}) {
46
107
  const {
47
108
  transformState,
48
109
  rootContainer = "#root",
49
- ssrWhenDev = true
110
+ ssrWhenDev = true,
111
+ getStyleCollector = null
50
112
  } = options;
51
113
  const isClient = typeof window !== "undefined";
52
114
  async function createRoot(client = false, routePath) {
@@ -58,7 +120,6 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
58
120
  return Promise.all(appRenderCallbacks.map((cb) => cb()));
59
121
  };
60
122
  const context = {
61
- // app: App,
62
123
  isClient,
63
124
  routes: routerOptions.routes,
64
125
  router: browserRouter,
@@ -67,7 +128,8 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
67
128
  triggerOnSSRAppRendered,
68
129
  initialState: {},
69
130
  transformState,
70
- routePath
131
+ routePath,
132
+ getStyleCollector
71
133
  };
72
134
  if (client) {
73
135
  await documentReady();
@@ -106,4 +168,6 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
106
168
 
107
169
  exports.Head = SiteMetadataDefaults.Head;
108
170
  exports.ClientOnly = ClientOnly;
171
+ exports.Link = Link;
172
+ exports.NavLink = NavLink;
109
173
  exports.ViteReactSSG = ViteReactSSG;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { R as RouterOptions, V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from './types-25b96ed0.js';
2
- export { I as IndexRouteRecord, N as NonIndexRouteRecord, c as RouteRecord, b as ViteReactSSGOptions } from './types-25b96ed0.js';
3
- import { ReactNode } from 'react';
1
+ import { R as RouterOptions, V as ViteReactSSGContext, a as ViteReactSSGClientOptions } from './types-408e974a.js';
2
+ export { I as IndexRouteRecord, N as NonIndexRouteRecord, c as RouteRecord, S as StyleCollector, b as ViteReactSSGOptions } from './types-408e974a.js';
3
+ import React, { ReactNode } from 'react';
4
4
  import { HelmetProps } from 'react-helmet-async';
5
+ import { LinkProps, NavLinkProps } from 'react-router-dom';
5
6
  import 'critters';
6
- import 'react-router-dom';
7
7
 
8
8
  type Props = HelmetProps & {
9
9
  children: ReactNode;
@@ -16,6 +16,9 @@ interface ClientOnlyProps {
16
16
  }
17
17
  declare function ClientOnly({ children, fallback, }: ClientOnlyProps): JSX.Element | null;
18
18
 
19
+ declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
20
+ declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefAttributes<HTMLAnchorElement>>;
21
+
19
22
  declare function ViteReactSSG(routerOptions: RouterOptions, fn?: (context: ViteReactSSGContext<true>) => Promise<void> | void, options?: ViteReactSSGClientOptions): (client?: boolean, routePath?: string) => Promise<ViteReactSSGContext<true>>;
20
23
 
21
- export { ClientOnly, Head, RouterOptions, ViteReactSSG, ViteReactSSGClientOptions, ViteReactSSGContext };
24
+ export { ClientOnly, Head, Link, NavLink, RouterOptions, ViteReactSSG, ViteReactSSGClientOptions, ViteReactSSGContext };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import React, { useState, useEffect, isValidElement } from 'react';
1
+ import React, { useState, useEffect, isValidElement, forwardRef } from 'react';
2
2
  import { createRoot, hydrateRoot } from 'react-dom/client';
3
3
  import { HelmetProvider } from 'react-helmet-async';
4
- import { createBrowserRouter, RouterProvider } from 'react-router-dom';
4
+ import { useLinkClickHandler, Link as Link$1, NavLink as NavLink$1, createBrowserRouter, RouterProvider } from 'react-router-dom';
5
5
  import { d as deserializeState, S as SiteMetadataDefaults } from './shared/vite-react-ssg.9d005d5e.mjs';
6
6
  export { H as Head } from './shared/vite-react-ssg.9d005d5e.mjs';
7
7
 
@@ -37,11 +37,73 @@ Current type: ${isValidElement(children) ? "React element" : typeof children}`);
37
37
  return fallback ?? null;
38
38
  }
39
39
 
40
+ const Link = forwardRef((props, ref) => {
41
+ const {
42
+ replace,
43
+ state,
44
+ target,
45
+ preventScrollReset,
46
+ relative,
47
+ to,
48
+ onClick
49
+ } = props;
50
+ const internalOnClick = useLinkClickHandler(to, {
51
+ replace,
52
+ state,
53
+ target,
54
+ preventScrollReset,
55
+ relative
56
+ });
57
+ function handleClick(event) {
58
+ if (onClick)
59
+ onClick(event);
60
+ if (!event.defaultPrevented) {
61
+ React.startTransition(() => {
62
+ internalOnClick(event);
63
+ });
64
+ }
65
+ event.defaultPrevented = true;
66
+ event.preventDefault();
67
+ }
68
+ return /* @__PURE__ */ React.createElement(Link$1, { ...props, ref, onClick: handleClick });
69
+ });
70
+ const NavLink = forwardRef((props, ref) => {
71
+ const {
72
+ replace,
73
+ state,
74
+ target,
75
+ preventScrollReset,
76
+ relative,
77
+ to,
78
+ onClick
79
+ } = props;
80
+ const internalOnClick = useLinkClickHandler(to, {
81
+ replace,
82
+ state,
83
+ target,
84
+ preventScrollReset,
85
+ relative
86
+ });
87
+ function handleClick(event) {
88
+ if (onClick)
89
+ onClick(event);
90
+ if (!event.defaultPrevented) {
91
+ React.startTransition(() => {
92
+ internalOnClick(event);
93
+ });
94
+ }
95
+ event.defaultPrevented = true;
96
+ event.preventDefault();
97
+ }
98
+ return /* @__PURE__ */ React.createElement(NavLink$1, { ...props, ref, onClick: handleClick });
99
+ });
100
+
40
101
  function ViteReactSSG(routerOptions, fn, options = {}) {
41
102
  const {
42
103
  transformState,
43
104
  rootContainer = "#root",
44
- ssrWhenDev = true
105
+ ssrWhenDev = true,
106
+ getStyleCollector = null
45
107
  } = options;
46
108
  const isClient = typeof window !== "undefined";
47
109
  async function createRoot$1(client = false, routePath) {
@@ -53,7 +115,6 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
53
115
  return Promise.all(appRenderCallbacks.map((cb) => cb()));
54
116
  };
55
117
  const context = {
56
- // app: App,
57
118
  isClient,
58
119
  routes: routerOptions.routes,
59
120
  router: browserRouter,
@@ -62,7 +123,8 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
62
123
  triggerOnSSRAppRendered,
63
124
  initialState: {},
64
125
  transformState,
65
- routePath
126
+ routePath,
127
+ getStyleCollector
66
128
  };
67
129
  if (client) {
68
130
  await documentReady();
@@ -99,4 +161,4 @@ function ViteReactSSG(routerOptions, fn, options = {}) {
99
161
  return createRoot$1;
100
162
  }
101
163
 
102
- export { ClientOnly, ViteReactSSG };
164
+ export { ClientOnly, Link, NavLink, ViteReactSSG };
package/dist/node/cli.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  const kolorist = require('kolorist');
4
4
  const yargs = require('yargs');
5
5
  const helpers = require('yargs/helpers');
6
- const dev = require('../shared/vite-react-ssg.823b31c9.cjs');
6
+ const dev = require('../shared/vite-react-ssg.8cbf43cc.cjs');
7
7
  require('node:path');
8
8
  require('node:module');
9
9
  require('fs-extra');
package/dist/node/cli.mjs CHANGED
@@ -1,7 +1,7 @@
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.7ee042ba.mjs';
4
+ import { b as build, d as dev } from '../shared/vite-react-ssg.5291bf32.mjs';
5
5
  import 'node:path';
6
6
  import 'node:module';
7
7
  import 'fs-extra';
package/dist/node.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const dev = require('./shared/vite-react-ssg.823b31c9.cjs');
3
+ const dev = require('./shared/vite-react-ssg.8cbf43cc.cjs');
4
4
  require('node:path');
5
5
  require('node:module');
6
6
  require('kolorist');
package/dist/node.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './types-25b96ed0.js';
2
+ import { b as ViteReactSSGOptions } from './types-408e974a.js';
3
3
  import 'critters';
4
+ import 'react';
4
5
  import 'react-router-dom';
5
6
 
6
7
  declare function build(ssgOptions?: Partial<ViteReactSSGOptions>, viteConfig?: InlineConfig): Promise<void>;
package/dist/node.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { b as build, d as dev } from './shared/vite-react-ssg.7ee042ba.mjs';
1
+ export { b as build, d as dev } from './shared/vite-react-ssg.5291bf32.mjs';
2
2
  import 'node:path';
3
3
  import 'node:module';
4
4
  import 'kolorist';
@@ -990,14 +990,16 @@ class WritableAsPromise extends Writable {
990
990
  }
991
991
  }
992
992
 
993
- async function render(routes, request) {
993
+ async function render(routes, request, styleCollector) {
994
994
  const { dataRoutes, query } = createStaticHandler(routes);
995
995
  const context = await query(request);
996
996
  const helmetContext = {};
997
997
  if (context instanceof Response)
998
998
  throw context;
999
999
  const router = createStaticRouter(dataRoutes, context);
1000
- const app = /* @__PURE__ */ React.createElement(HelmetProvider, { context: helmetContext }, /* @__PURE__ */ React.createElement(SiteMetadataDefaults, null), /* @__PURE__ */ React.createElement(StaticRouterProvider, { router, context }));
1000
+ let app = /* @__PURE__ */ React.createElement(HelmetProvider, { context: helmetContext }, /* @__PURE__ */ React.createElement(SiteMetadataDefaults, null), /* @__PURE__ */ React.createElement(StaticRouterProvider, { router, context }));
1001
+ if (styleCollector)
1002
+ app = styleCollector.collect(app);
1001
1003
  const appHTML = await renderStaticApp(app);
1002
1004
  const { helmet } = helmetContext;
1003
1005
  const htmlAttributes = helmet.htmlAttributes.toString();
@@ -1008,6 +1010,8 @@ async function render(routes, request) {
1008
1010
  helmet.link.toString(),
1009
1011
  helmet.script.toString()
1010
1012
  ];
1013
+ const styleTag = styleCollector?.toString?.(appHTML) ?? "";
1014
+ metaStrings.push(styleTag);
1011
1015
  const metaAttributes = metaStrings.filter(Boolean);
1012
1016
  return { appHTML, htmlAttributes, bodyAttributes, metaAttributes };
1013
1017
  }
@@ -1209,14 +1213,15 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1209
1213
  queue.add(async () => {
1210
1214
  try {
1211
1215
  const appCtx = await createRoot(false, route);
1212
- const { routes: routes2, initialState, triggerOnSSRAppRendered, transformState = serializeState } = appCtx;
1216
+ const { routes: routes2, initialState, triggerOnSSRAppRendered, transformState = serializeState, getStyleCollector } = appCtx;
1217
+ const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1213
1218
  const transformedIndexHTML = await onBeforePageRender?.(route, indexHTML, appCtx) || indexHTML;
1214
1219
  const url = new URL(route, "http://vite-react-ssg.com");
1215
1220
  url.search = "";
1216
1221
  url.hash = "";
1217
1222
  url.pathname = route;
1218
1223
  const request = new Request(url.href);
1219
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes2], request);
1224
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes2], request, styleCollector);
1220
1225
  await triggerOnSSRAppRendered?.(route, appHTML, appCtx);
1221
1226
  const renderedHTML = await renderHTML({
1222
1227
  rootContainerId,
@@ -1410,9 +1415,10 @@ async function dev(ssgOptions = {}, viteConfig = {}) {
1410
1415
  const indexHTML = await viteServer.transformIndexHtml(url, template);
1411
1416
  const createRoot = await viteServer.ssrLoadModule(ssrEntry).then((m) => m.createRoot);
1412
1417
  const appCtx = await createRoot(false, url);
1413
- const { routes } = appCtx;
1418
+ const { routes, getStyleCollector } = appCtx;
1414
1419
  const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1415
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes], createFetchRequest(req));
1420
+ const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1421
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes], createFetchRequest(req), styleCollector);
1416
1422
  const mod = await viteServer.moduleGraph.getModuleByUrl(entry);
1417
1423
  const assetsUrls = /* @__PURE__ */ new Set();
1418
1424
  const collectAssets = async (mod2) => {
@@ -934,7 +934,7 @@ async function resolveAlias(config, entry) {
934
934
  return result || node_path.join(config.root, entry);
935
935
  }
936
936
  const { version } = JSON.parse(
937
- node_fs.readFileSync(new URL("../../package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('shared/vite-react-ssg.823b31c9.cjs', document.baseURI).href)))).toString()
937
+ node_fs.readFileSync(new URL("../../package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('shared/vite-react-ssg.8cbf43cc.cjs', document.baseURI).href)))).toString()
938
938
  );
939
939
 
940
940
  async function getCritters(outDir, options = {}) {
@@ -998,14 +998,16 @@ class WritableAsPromise extends node_stream.Writable {
998
998
  }
999
999
  }
1000
1000
 
1001
- async function render(routes, request) {
1001
+ async function render(routes, request, styleCollector) {
1002
1002
  const { dataRoutes, query } = server_js.createStaticHandler(routes);
1003
1003
  const context = await query(request);
1004
1004
  const helmetContext = {};
1005
1005
  if (context instanceof Response)
1006
1006
  throw context;
1007
1007
  const router = server_js.createStaticRouter(dataRoutes, context);
1008
- const app = /* @__PURE__ */ React__default.createElement(reactHelmetAsync.HelmetProvider, { context: helmetContext }, /* @__PURE__ */ React__default.createElement(SiteMetadataDefaults.SiteMetadataDefaults, null), /* @__PURE__ */ React__default.createElement(server_js.StaticRouterProvider, { router, context }));
1008
+ let app = /* @__PURE__ */ React__default.createElement(reactHelmetAsync.HelmetProvider, { context: helmetContext }, /* @__PURE__ */ React__default.createElement(SiteMetadataDefaults.SiteMetadataDefaults, null), /* @__PURE__ */ React__default.createElement(server_js.StaticRouterProvider, { router, context }));
1009
+ if (styleCollector)
1010
+ app = styleCollector.collect(app);
1009
1011
  const appHTML = await renderStaticApp(app);
1010
1012
  const { helmet } = helmetContext;
1011
1013
  const htmlAttributes = helmet.htmlAttributes.toString();
@@ -1016,6 +1018,8 @@ async function render(routes, request) {
1016
1018
  helmet.link.toString(),
1017
1019
  helmet.script.toString()
1018
1020
  ];
1021
+ const styleTag = styleCollector?.toString?.(appHTML) ?? "";
1022
+ metaStrings.push(styleTag);
1019
1023
  const metaAttributes = metaStrings.filter(Boolean);
1020
1024
  return { appHTML, htmlAttributes, bodyAttributes, metaAttributes };
1021
1025
  }
@@ -1197,7 +1201,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1197
1201
  const prefix = format === "esm" && process.platform === "win32" ? "file://" : "";
1198
1202
  const ext = format === "esm" ? ".mjs" : ".cjs";
1199
1203
  const serverEntry = node_path.join(prefix, ssgOut, node_path.parse(ssrEntry).name + ext);
1200
- const _require = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('shared/vite-react-ssg.823b31c9.cjs', document.baseURI).href)));
1204
+ const _require = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('shared/vite-react-ssg.8cbf43cc.cjs', document.baseURI).href)));
1201
1205
  const { createRoot, includedRoutes: serverEntryIncludedRoutes } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
1202
1206
  const includedRoutes = serverEntryIncludedRoutes || configIncludedRoutes;
1203
1207
  const { routes } = await createRoot(false);
@@ -1217,14 +1221,15 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1217
1221
  queue.add(async () => {
1218
1222
  try {
1219
1223
  const appCtx = await createRoot(false, route);
1220
- const { routes: routes2, initialState, triggerOnSSRAppRendered, transformState = SiteMetadataDefaults.serializeState } = appCtx;
1224
+ const { routes: routes2, initialState, triggerOnSSRAppRendered, transformState = SiteMetadataDefaults.serializeState, getStyleCollector } = appCtx;
1225
+ const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1221
1226
  const transformedIndexHTML = await onBeforePageRender?.(route, indexHTML, appCtx) || indexHTML;
1222
1227
  const url = new URL(route, "http://vite-react-ssg.com");
1223
1228
  url.search = "";
1224
1229
  url.hash = "";
1225
1230
  url.pathname = route;
1226
1231
  const request = new Request(url.href);
1227
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes2], request);
1232
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes2], request, styleCollector);
1228
1233
  await triggerOnSSRAppRendered?.(route, appHTML, appCtx);
1229
1234
  const renderedHTML = await renderHTML({
1230
1235
  rootContainerId,
@@ -1418,9 +1423,10 @@ async function dev(ssgOptions = {}, viteConfig = {}) {
1418
1423
  const indexHTML = await viteServer.transformIndexHtml(url, template);
1419
1424
  const createRoot = await viteServer.ssrLoadModule(ssrEntry).then((m) => m.createRoot);
1420
1425
  const appCtx = await createRoot(false, url);
1421
- const { routes } = appCtx;
1426
+ const { routes, getStyleCollector } = appCtx;
1422
1427
  const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1423
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes], createFetchRequest(req));
1428
+ const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1429
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes } = await render([...routes], createFetchRequest(req), styleCollector);
1424
1430
  const mod = await viteServer.moduleGraph.getModuleByUrl(entry);
1425
1431
  const assetsUrls = /* @__PURE__ */ new Set();
1426
1432
  const collectAssets = async (mod2) => {
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ async function ssrCollector() {
4
+ const { ServerStyleSheet } = await import('styled-components');
5
+ const sheet = new ServerStyleSheet();
6
+ return {
7
+ collect(app) {
8
+ return sheet.collectStyles(app);
9
+ },
10
+ toString() {
11
+ return sheet.getStyleTags();
12
+ },
13
+ cleanup() {
14
+ sheet.seal();
15
+ }
16
+ };
17
+ }
18
+ const styledComponents = undefined.SSR ? ssrCollector : null;
19
+
20
+ exports.getStyledComponentsCollector = styledComponents;
@@ -0,0 +1,10 @@
1
+ import { ReactElement } from 'react';
2
+
3
+ declare function ssrCollector(): Promise<{
4
+ collect(app: ReactElement): JSX.Element;
5
+ toString(): string;
6
+ cleanup(): void;
7
+ }>;
8
+ declare const _default: typeof ssrCollector | null;
9
+
10
+ export { _default as getStyledComponentsCollector };
@@ -0,0 +1,18 @@
1
+ async function ssrCollector() {
2
+ const { ServerStyleSheet } = await import('styled-components');
3
+ const sheet = new ServerStyleSheet();
4
+ return {
5
+ collect(app) {
6
+ return sheet.collectStyles(app);
7
+ },
8
+ toString() {
9
+ return sheet.getStyleTags();
10
+ },
11
+ cleanup() {
12
+ sheet.seal();
13
+ }
14
+ };
15
+ }
16
+ const styledComponents = import.meta.env.SSR ? ssrCollector : null;
17
+
18
+ export { styledComponents as getStyledComponentsCollector };
@@ -1,4 +1,5 @@
1
1
  import { Options } from 'critters';
2
+ import { ReactElement } from 'react';
2
3
  import { NonIndexRouteObject, IndexRouteObject, createBrowserRouter } from 'react-router-dom';
3
4
 
4
5
  type Router = ReturnType<typeof createBrowserRouter>;
@@ -116,6 +117,7 @@ interface ViteReactSSGContext<HasRouter extends boolean = true> {
116
117
  * Current router path on SSG, `undefined` on client side.
117
118
  */
118
119
  routePath?: string;
120
+ getStyleCollector: (() => StyleCollector | Promise<StyleCollector>) | null;
119
121
  }
120
122
  interface ViteReactSSGClientOptions {
121
123
  transformState?: (state: any) => any;
@@ -134,6 +136,7 @@ interface ViteReactSSGClientOptions {
134
136
  * @default true
135
137
  */
136
138
  ssrWhenDev?: boolean;
139
+ getStyleCollector?: (() => StyleCollector | Promise<StyleCollector>) | null;
137
140
  }
138
141
  interface CommonRouteOptions {
139
142
  /**
@@ -152,10 +155,15 @@ interface RouterOptions {
152
155
  routes: RouteRecord[];
153
156
  createFetchRequest?: <T>(req: T) => Request;
154
157
  }
158
+ interface StyleCollector {
159
+ collect: (app: ReactElement) => ReactElement;
160
+ toString: (html: string) => string;
161
+ cleanup?: () => void;
162
+ }
155
163
  declare module 'vite' {
156
164
  interface UserConfig {
157
165
  ssgOptions?: ViteReactSSGOptions;
158
166
  }
159
167
  }
160
168
 
161
- export { IndexRouteRecord as I, NonIndexRouteRecord as N, RouterOptions as R, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, ViteReactSSGOptions as b, RouteRecord as c };
169
+ export { IndexRouteRecord as I, NonIndexRouteRecord as N, RouterOptions as R, StyleCollector as S, ViteReactSSGContext as V, ViteReactSSGClientOptions as a, ViteReactSSGOptions as b, RouteRecord as c };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-react-ssg",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "packageManager": "pnpm@8.6.6",
6
6
  "description": "",
7
7
  "author": "Riri <Daydreamerriri@outlook.com>",
@@ -30,6 +30,11 @@
30
30
  "types": "./dist/node.d.ts",
31
31
  "require": "./dist/node.cjs",
32
32
  "import": "./dist/node.mjs"
33
+ },
34
+ "./style-collectors": {
35
+ "types": "./dist/style-collectors.d.ts",
36
+ "require": "./dist/style-collectors.cjs",
37
+ "import": "./dist/style-collectors.mjs"
33
38
  }
34
39
  },
35
40
  "main": "./dist/index.mjs",
@@ -39,6 +44,9 @@
39
44
  "*": {
40
45
  "node": [
41
46
  "./dist/node.d.ts"
47
+ ],
48
+ "style-collectors": [
49
+ "./dist/style-collectors.d.ts"
42
50
  ]
43
51
  }
44
52
  },
@@ -64,6 +72,7 @@
64
72
  "react": "^18.0.0",
65
73
  "react-dom": "^18.0.0",
66
74
  "react-router-dom": "^6.14.1",
75
+ "styled-components": "^6.0.0",
67
76
  "vite": "^2.0.0 || ^3.0.0 || ^4.0.0"
68
77
  },
69
78
  "peerDependenciesMeta": {
@@ -72,6 +81,9 @@
72
81
  },
73
82
  "react-router-dom": {
74
83
  "optional": true
84
+ },
85
+ "styled-components": {
86
+ "optional": true
75
87
  }
76
88
  },
77
89
  "dependencies": {
@@ -106,6 +118,7 @@
106
118
  "react-router-dom": "^6.14.1",
107
119
  "rimraf": "5.0.1",
108
120
  "simple-git-hooks": "^2.8.1",
121
+ "styled-components": "6.0.5",
109
122
  "typescript": "5.1.6",
110
123
  "unbuild": "^1.2.1",
111
124
  "vite": "^4.4.0",