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 +16 -1
- package/dist/index.cjs +67 -3
- package/dist/index.d.ts +8 -5
- package/dist/index.mjs +68 -6
- package/dist/node/cli.cjs +1 -1
- package/dist/node/cli.mjs +1 -1
- package/dist/node.cjs +1 -1
- package/dist/node.d.ts +2 -1
- package/dist/node.mjs +1 -1
- package/dist/shared/{vite-react-ssg.7ee042ba.mjs → vite-react-ssg.5291bf32.mjs} +12 -6
- package/dist/shared/{vite-react-ssg.823b31c9.cjs → vite-react-ssg.8cbf43cc.cjs} +14 -8
- package/dist/style-collectors.cjs +20 -0
- package/dist/style-collectors.d.ts +10 -0
- package/dist/style-collectors.mjs +18 -0
- package/dist/{types-25b96ed0.d.ts → types-408e974a.d.ts} +9 -1
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ function MyComponent() {
|
|
|
100
100
|
}
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
> It's important that the children of
|
|
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-
|
|
2
|
-
export { I as IndexRouteRecord, N as NonIndexRouteRecord, c as RouteRecord, b as ViteReactSSGOptions } from './types-
|
|
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.
|
|
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.
|
|
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
package/dist/node.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InlineConfig } from 'vite';
|
|
2
|
-
import { b as ViteReactSSGOptions } from './types-
|
|
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
|
@@ -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
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
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.
|
|
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",
|