vike-react 0.6.16 → 0.6.18
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/dist/components/ClientOnly.d.ts +12 -9
- package/dist/components/ClientOnly.js +18 -24
- package/dist/config.d.ts +45 -0
- package/dist/config.js +37 -1
- package/dist/helpers/clientOnly.js +2 -0
- package/dist/hooks/useConfig/useConfig-server.js +6 -3
- package/dist/hooks/useHydrated.d.ts +19 -0
- package/dist/hooks/useHydrated.js +26 -0
- package/package.json +7 -3
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
export { ClientOnly };
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Render children only on the client-side.
|
|
6
|
+
*
|
|
7
|
+
* Children are completely removed and never loaded on the server.
|
|
8
|
+
*
|
|
9
|
+
* https://vike.dev/ClientOnly
|
|
10
|
+
*/
|
|
11
|
+
declare function ClientOnly({ children, fallback }: {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
fallback?: ReactNode;
|
|
14
|
+
}): React.JSX.Element;
|
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
export { ClientOnly };
|
|
2
|
-
import React
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
startTransition(() => {
|
|
22
|
-
loadComponent();
|
|
23
|
-
});
|
|
24
|
-
}, deps);
|
|
25
|
-
return Component ? React.createElement(Component, null) : fallback;
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { usePageContext } from '../hooks/usePageContext.js';
|
|
4
|
+
import { useHydrated } from '../hooks/useHydrated.js';
|
|
5
|
+
import { assert } from '../utils/assert.js';
|
|
6
|
+
/**
|
|
7
|
+
* Render children only on the client-side.
|
|
8
|
+
*
|
|
9
|
+
* Children are completely removed and never loaded on the server.
|
|
10
|
+
*
|
|
11
|
+
* https://vike.dev/ClientOnly
|
|
12
|
+
*/
|
|
13
|
+
function ClientOnly({ children, fallback }) {
|
|
14
|
+
const pageContext = usePageContext();
|
|
15
|
+
// Assert tree-shaking: children should be statically removed on the server-side
|
|
16
|
+
if (!pageContext.isClientSide)
|
|
17
|
+
assert(children === undefined);
|
|
18
|
+
const hydrated = useHydrated();
|
|
19
|
+
return React.createElement(React.Fragment, null, hydrated ? children : fallback);
|
|
26
20
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -11,6 +11,51 @@ declare const config: {
|
|
|
11
11
|
passToClient: string[];
|
|
12
12
|
clientRouting: true;
|
|
13
13
|
hydrationCanBeAborted: true;
|
|
14
|
+
staticReplace: ({
|
|
15
|
+
env: "server";
|
|
16
|
+
filter: string;
|
|
17
|
+
type: "call";
|
|
18
|
+
match: {
|
|
19
|
+
function: string[];
|
|
20
|
+
args: {
|
|
21
|
+
0: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
remove: {
|
|
25
|
+
arg: number;
|
|
26
|
+
prop: string;
|
|
27
|
+
argsFrom?: undefined;
|
|
28
|
+
};
|
|
29
|
+
replace?: undefined;
|
|
30
|
+
} | {
|
|
31
|
+
env: "server";
|
|
32
|
+
filter: string;
|
|
33
|
+
type: "call";
|
|
34
|
+
match: {
|
|
35
|
+
function: string;
|
|
36
|
+
args: {
|
|
37
|
+
0: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
remove: {
|
|
41
|
+
argsFrom: number;
|
|
42
|
+
arg?: undefined;
|
|
43
|
+
prop?: undefined;
|
|
44
|
+
};
|
|
45
|
+
replace?: undefined;
|
|
46
|
+
} | {
|
|
47
|
+
env: "server";
|
|
48
|
+
filter: string;
|
|
49
|
+
type: "call";
|
|
50
|
+
match: {
|
|
51
|
+
function: string;
|
|
52
|
+
args?: undefined;
|
|
53
|
+
};
|
|
54
|
+
replace: {
|
|
55
|
+
with: boolean;
|
|
56
|
+
};
|
|
57
|
+
remove?: undefined;
|
|
58
|
+
})[];
|
|
14
59
|
meta: {
|
|
15
60
|
Head: {
|
|
16
61
|
env: {
|
package/dist/config.js
CHANGED
|
@@ -5,7 +5,7 @@ const config = {
|
|
|
5
5
|
// @eject-remove start
|
|
6
6
|
name: 'vike-react',
|
|
7
7
|
require: {
|
|
8
|
-
vike: '>=0.4.
|
|
8
|
+
vike: '>=0.4.250',
|
|
9
9
|
},
|
|
10
10
|
Loading: 'import:vike-react/__internal/integration/Loading:default',
|
|
11
11
|
// https://vike.dev/onRenderHtml
|
|
@@ -21,6 +21,42 @@ const config = {
|
|
|
21
21
|
// https://vike.dev/clientRouting
|
|
22
22
|
clientRouting: true,
|
|
23
23
|
hydrationCanBeAborted: true,
|
|
24
|
+
// Remove <ClientOnly> children on server
|
|
25
|
+
staticReplace: [
|
|
26
|
+
{
|
|
27
|
+
env: 'server',
|
|
28
|
+
filter: 'vike-react/ClientOnly',
|
|
29
|
+
type: 'call',
|
|
30
|
+
match: {
|
|
31
|
+
function: [
|
|
32
|
+
'import:react/jsx-runtime:jsx',
|
|
33
|
+
'import:react/jsx-runtime:jsxs',
|
|
34
|
+
'import:react/jsx-dev-runtime:jsxDEV',
|
|
35
|
+
],
|
|
36
|
+
args: { 0: 'import:vike-react/ClientOnly:ClientOnly' },
|
|
37
|
+
},
|
|
38
|
+
remove: { arg: 1, prop: 'children' },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
env: 'server',
|
|
42
|
+
filter: 'vike-react/ClientOnly',
|
|
43
|
+
type: 'call',
|
|
44
|
+
match: {
|
|
45
|
+
function: 'import:react:createElement',
|
|
46
|
+
args: { 0: 'import:vike-react/ClientOnly:ClientOnly' },
|
|
47
|
+
},
|
|
48
|
+
remove: { argsFrom: 2 },
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
env: 'server',
|
|
52
|
+
filter: 'vike-react/useHydrated',
|
|
53
|
+
type: 'call',
|
|
54
|
+
match: {
|
|
55
|
+
function: 'import:vike-react/useHydrated:useHydrated',
|
|
56
|
+
},
|
|
57
|
+
replace: { with: false },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
24
60
|
// https://vike.dev/meta
|
|
25
61
|
meta: {
|
|
26
62
|
Head: {
|
|
@@ -18,6 +18,7 @@ function useConfig() {
|
|
|
18
18
|
return (config) => setPageContextConfigViaHook(config, pageContext);
|
|
19
19
|
// Component
|
|
20
20
|
pageContext = usePageContext();
|
|
21
|
+
assert(!pageContext.isClientSide);
|
|
21
22
|
const stream = useStreamOptional();
|
|
22
23
|
return (config) => {
|
|
23
24
|
if (!pageContext._headAlreadySet) {
|
|
@@ -26,7 +27,7 @@ function useConfig() {
|
|
|
26
27
|
else {
|
|
27
28
|
assert(stream);
|
|
28
29
|
// <head> already sent to the browser => send DOM-manipulating scripts during HTML streaming
|
|
29
|
-
apply(config, stream);
|
|
30
|
+
apply(config, stream, pageContext);
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
}
|
|
@@ -55,10 +56,12 @@ function setPageContextConfigViaHook(config, pageContext) {
|
|
|
55
56
|
}
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
|
-
function apply(config, stream) {
|
|
59
|
+
function apply(config, stream, pageContext) {
|
|
59
60
|
const { title } = config;
|
|
60
61
|
if (title) {
|
|
61
|
-
|
|
62
|
+
// No need to escape the injected HTML — see https://github.com/vikejs/vike/blob/36201ddad5f5b527b244b24d548014ec86c204e4/packages/vike/src/server/runtime/renderPageServer/csp.ts#L45
|
|
63
|
+
const nonceAttr = pageContext.cspNonce ? ` nonce="${pageContext.cspNonce}"` : '';
|
|
64
|
+
const htmlSnippet = `<script${nonceAttr}>document.title = ${JSON.stringify(title)}</script>`;
|
|
62
65
|
stream.injectToStream(htmlSnippet);
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { useHydrated };
|
|
2
|
+
/**
|
|
3
|
+
* Whether the page has already been hydrated.
|
|
4
|
+
*
|
|
5
|
+
* On the server, it always returns `false`. On the client, it returns `false` on first render and `true` after hydration completes.
|
|
6
|
+
*
|
|
7
|
+
* https://vike.dev/useHydrated
|
|
8
|
+
*
|
|
9
|
+
* Example: Disable a button that needs JavaScript to work.
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const hydrated = useHydrated()
|
|
12
|
+
* return (
|
|
13
|
+
* <button type="button" disabled={!hydrated} onClick={doSomething}>
|
|
14
|
+
* Click me
|
|
15
|
+
* </button>
|
|
16
|
+
* );
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function useHydrated(): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { useHydrated };
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
|
+
// Copied from https://github.com/sergiodxa/remix-utils/blob/33e6b04a08ef5f9b65e89c0a280c12b83762ef66/src/react/use-hydrated.ts
|
|
4
|
+
/**
|
|
5
|
+
* Whether the page has already been hydrated.
|
|
6
|
+
*
|
|
7
|
+
* On the server, it always returns `false`. On the client, it returns `false` on first render and `true` after hydration completes.
|
|
8
|
+
*
|
|
9
|
+
* https://vike.dev/useHydrated
|
|
10
|
+
*
|
|
11
|
+
* Example: Disable a button that needs JavaScript to work.
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const hydrated = useHydrated()
|
|
14
|
+
* return (
|
|
15
|
+
* <button type="button" disabled={!hydrated} onClick={doSomething}>
|
|
16
|
+
* Click me
|
|
17
|
+
* </button>
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
function useHydrated() {
|
|
22
|
+
return useSyncExternalStore(subscribeDummy, () => true, () => false);
|
|
23
|
+
}
|
|
24
|
+
function subscribeDummy() {
|
|
25
|
+
return () => { };
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vike-react",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.18",
|
|
4
4
|
"repository": "https://github.com/vikejs/vike-react",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./usePageContext": "./dist/hooks/usePageContext.js",
|
|
8
8
|
"./useData": "./dist/hooks/useData.js",
|
|
9
|
+
"./useHydrated": "./dist/hooks/useHydrated.js",
|
|
9
10
|
"./useConfig": {
|
|
10
11
|
"browser": "./dist/hooks/useConfig/useConfig-client.js",
|
|
11
12
|
"default": "./dist/hooks/useConfig/useConfig-server.js"
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"peerDependencies": {
|
|
33
34
|
"react": ">=19",
|
|
34
35
|
"react-dom": ">=19",
|
|
35
|
-
"vike": ">=0.4.
|
|
36
|
+
"vike": ">=0.4.250"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@biomejs/biome": "^1.9.4",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"react-dom": "^19.2.1",
|
|
45
46
|
"rimraf": "^5.0.5",
|
|
46
47
|
"typescript": "^5.9.2",
|
|
47
|
-
"vike": "^0.4.
|
|
48
|
+
"vike": "^0.4.250",
|
|
48
49
|
"vite": "^7.3.0"
|
|
49
50
|
},
|
|
50
51
|
"typesVersions": {
|
|
@@ -55,6 +56,9 @@
|
|
|
55
56
|
"usePageContext": [
|
|
56
57
|
"./dist/hooks/usePageContext.d.ts"
|
|
57
58
|
],
|
|
59
|
+
"useHydrated": [
|
|
60
|
+
"./dist/hooks/useHydrated.d.ts"
|
|
61
|
+
],
|
|
58
62
|
"useConfig": [
|
|
59
63
|
"./dist/hooks/useConfig/useConfig-server.d.ts"
|
|
60
64
|
],
|