vike-react-rsc-rudder 1.0.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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/cache-BCYpxG4P.js +164 -0
- package/dist/client-BpZo3JRu.js +86 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +53 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.js +875 -0
- package/dist/constants.d.ts +1 -0
- package/dist/getGlobalObject-CzWO6NfD.js +10 -0
- package/dist/hooks/pageContext/pageContext-client.d.ts +11 -0
- package/dist/hooks/pageContext/pageContext-client.js +4 -0
- package/dist/hooks/pageContext/pageContext-server.d.ts +7 -0
- package/dist/hooks/pageContext/pageContext-server.js +4 -0
- package/dist/integration/client.d.ts +1 -0
- package/dist/integration/client.js +16 -0
- package/dist/integration/getPageElement/getPageElement-server.d.ts +14 -0
- package/dist/integration/onBeforeRender.d.ts +2 -0
- package/dist/integration/onBeforeRender.js +17 -0
- package/dist/integration/onPageTransitionStart.d.ts +2 -0
- package/dist/integration/onPageTransitionStart.js +11 -0
- package/dist/integration/onRenderClient.d.ts +2 -0
- package/dist/integration/onRenderClient.js +63 -0
- package/dist/integration/onRenderHtml.d.ts +2 -0
- package/dist/integration/onRenderHtml.js +10 -0
- package/dist/integration/rscMiddleware.d.ts +3 -0
- package/dist/integration/rscMiddleware.js +35 -0
- package/dist/pageContext-client-CmvZ4bmk.js +27 -0
- package/dist/pageContext-server-B1QwrAws.js +22 -0
- package/dist/plugin/index.d.ts +20 -0
- package/dist/plugin/plugins/clientDepTrackerPlugin.d.ts +7 -0
- package/dist/plugin/plugins/config.d.ts +8 -0
- package/dist/plugin/plugins/cssTrackerPlugin.d.ts +6 -0
- package/dist/plugin/plugins/dev.d.ts +2 -0
- package/dist/plugin/plugins/hmrPlugin.d.ts +2 -0
- package/dist/plugin/plugins/injectManifestBuild.d.ts +6 -0
- package/dist/plugin/plugins/serverComponentExclusionPlugin.d.ts +6 -0
- package/dist/plugin/plugins/useClientPlugin.d.ts +2 -0
- package/dist/plugin/plugins/useServerPlugin.d.ts +2 -0
- package/dist/plugin/plugins/virtuals.d.ts +2 -0
- package/dist/plugin/utils.d.ts +6 -0
- package/dist/register/browser.d.ts +1 -0
- package/dist/register/browser.js +3 -0
- package/dist/register/server.d.ts +1 -0
- package/dist/register/server.js +3 -0
- package/dist/register/ssr.d.ts +1 -0
- package/dist/register/ssr.js +3 -0
- package/dist/runtime/cache.d.ts +50 -0
- package/dist/runtime/client/globalState.d.ts +22 -0
- package/dist/runtime/client.d.ts +5 -0
- package/dist/runtime/rscBridge.d.ts +7 -0
- package/dist/runtime/server.d.ts +7 -0
- package/dist/runtime/server.js +110 -0
- package/dist/runtime/serverActionContext.d.ts +23 -0
- package/dist/runtime/ssr.d.ts +2 -0
- package/dist/runtime/ssr.js +107 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +4 -0
- package/dist/serverActionContext-7Jnbh0-W.js +38 -0
- package/dist/types/Config.d.ts +59 -0
- package/dist/types.d.ts +22 -0
- package/dist/utils/getGlobalObject.d.ts +1 -0
- package/dist/utils/isReactElement.d.ts +5 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) nitedani and vike-react-rsc contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# `vike-react-rsc-rudder`
|
|
2
|
+
|
|
3
|
+
React Server Components support for [Vike](https://vike.dev). This is a
|
|
4
|
+
**RudderJS-maintained fork** of [`vike-react-rsc`](https://github.com/nitedani/vike-react-rsc)
|
|
5
|
+
by **nitedani**, **MIT-licensed** (see `LICENSE`). Copyright for the original
|
|
6
|
+
work remains with nitedani and contributors; the fork's changes are documented
|
|
7
|
+
below.
|
|
8
|
+
|
|
9
|
+
## Why this fork exists
|
|
10
|
+
|
|
11
|
+
The working version of the upstream package (`1.0.0`) lives **only** in the
|
|
12
|
+
GitHub repository — npm has nothing but a `0.0.0` stub published in 2024-04, and
|
|
13
|
+
the upstream "Publish?" request ([issue #3](https://github.com/nitedani/vike-react-rsc/issues/3),
|
|
14
|
+
2025-11-13) is unanswered. RudderJS's RSC integration needs an installable,
|
|
15
|
+
versioned package, so we publish this maintained fork.
|
|
16
|
+
|
|
17
|
+
### Why the name isn't `@rudderjs/…`
|
|
18
|
+
|
|
19
|
+
Vike's config-extension mechanism only recognizes an extension's `extends`
|
|
20
|
+
import (and turns it into a pointer import) when the package name **starts with
|
|
21
|
+
`vike-`** — see `path.startsWith('vike-') && path.endsWith('/config')` in vike's
|
|
22
|
+
`transpileWithEsbuild`. A scoped `@rudderjs/…` name isn't detected, so apps
|
|
23
|
+
would have to add a `with { type: 'vike:pointer' }` attribute to the `extends`
|
|
24
|
+
import in every `+config.ts`. Keeping the unscoped `vike-*` convention (as
|
|
25
|
+
`vike-react`, `vike-vue`, … all do) means RSC apps wire it up with a plain
|
|
26
|
+
`extends: [vikeReactRsc]` and no per-app ceremony. The `-rudder` suffix marks
|
|
27
|
+
it as our fork and distinguishes it from upstream's `vike-react-rsc`.
|
|
28
|
+
|
|
29
|
+
It is consumed by `@rudderjs/vite`'s view scanner, which detects either
|
|
30
|
+
`vike-react-rsc-rudder` (preferred) or the legacy upstream `vike-react-rsc` name
|
|
31
|
+
and generates RSC page stubs that import from whichever is installed.
|
|
32
|
+
|
|
33
|
+
## Source
|
|
34
|
+
|
|
35
|
+
- Upstream: https://github.com/nitedani/vike-react-rsc
|
|
36
|
+
- Forked at commit: `094054c7649d70707b8f5749ca3e22e33a67801f` (2025-12-06,
|
|
37
|
+
upstream `main` HEAD as of forking)
|
|
38
|
+
|
|
39
|
+
## Changes from upstream
|
|
40
|
+
|
|
41
|
+
- `package.json`: renamed to `vike-react-rsc-rudder`; published publicly
|
|
42
|
+
(`publishConfig.access: public`); `@vitejs/plugin-rsc` moved from
|
|
43
|
+
`devDependencies` to `dependencies` (the build externalizes it, so consumers
|
|
44
|
+
need it at runtime); `react` / `react-dom` / `vite` / `vike` dev pins aligned
|
|
45
|
+
to the RudderJS monorepo versions.
|
|
46
|
+
- `src/constants.ts` + `src/config.ts`: the package self-references
|
|
47
|
+
(`PKG_NAME`, the vike config `name`, and the `import:…/__internal/…`
|
|
48
|
+
specifiers) updated to the fork package name.
|
|
49
|
+
- `src/config.ts`: config import strings name the export (`:default`) — vike
|
|
50
|
+
≥0.4.257 requires it; the upstream 1.0.0 (built against 0.4.246) omitted it,
|
|
51
|
+
which crashed vike's dev `optimizeDeps`.
|
|
52
|
+
- `src/config.ts`: the SSR build's `rollupOptions.input` also includes Vike's
|
|
53
|
+
server entry (`entry: serverEntryVirtualId`). Upstream targets `vike-server`
|
|
54
|
+
(no `+server.ts`); RudderJS uses the `+server.ts` → `app.fetch` model, where
|
|
55
|
+
`@brillout/vite-plugin-server-entry` needs that entry — otherwise the
|
|
56
|
+
production build fails with "Cannot find build server entry".
|
|
57
|
+
- `src/plugin/plugins/injectManifestBuild.ts`: the page-entry virtual id was
|
|
58
|
+
renamed by vike (`virtual:vike:pageConfigValuesAll:server:` →
|
|
59
|
+
`virtual:vike:page-entry:server:`, vike ≥0.4.257). Without the rename the
|
|
60
|
+
production RSC manifest is empty and rendering 500s ("Cannot read properties
|
|
61
|
+
of undefined (reading 'getConfig')"). The module shape
|
|
62
|
+
(`configValuesSerialized`) is unchanged.
|
|
63
|
+
- Added this file and `LICENSE` (the upstream repo ships no `LICENSE` file
|
|
64
|
+
despite declaring MIT in `package.json`).
|
|
65
|
+
|
|
66
|
+
Source is otherwise unmodified. Build: `tsdown --clean` (→ `dist/`). The vike
|
|
67
|
+
version-compat changes above (config import strings, the page-entry virtual id)
|
|
68
|
+
should be re-checked whenever vike is bumped.
|
|
69
|
+
|
|
70
|
+
## Re-syncing from upstream
|
|
71
|
+
|
|
72
|
+
Re-copy `src/`, `tsdown.config.ts`, and `tsconfig.json` from a newer upstream
|
|
73
|
+
commit, then re-apply the changes above. Update the commit hash in this file.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { getGlobalObject } from "./getGlobalObject-CzWO6NfD.js";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/client/globalState.ts
|
|
4
|
+
function getGlobalClientState() {
|
|
5
|
+
return getGlobalObject("globalState.ts", {
|
|
6
|
+
rscCache: new Map(),
|
|
7
|
+
serverComponentCache: new Map(),
|
|
8
|
+
pendingRequests: new Map(),
|
|
9
|
+
isRscCall: false
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/runtime/cache.ts
|
|
15
|
+
const DEFAULT_STALE_TIME = 60 * 1e3;
|
|
16
|
+
/**
|
|
17
|
+
* Get the cache key for a page context
|
|
18
|
+
*/
|
|
19
|
+
function getCacheKey(pageContext) {
|
|
20
|
+
return `${pageContext.urlPathname}${pageContext.urlParsed.searchOriginal || ""}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get stale time from page context
|
|
24
|
+
*/
|
|
25
|
+
function getStaleTime(pageContext) {
|
|
26
|
+
const userConfig = pageContext.config?.rsc;
|
|
27
|
+
return userConfig?.staleTime !== void 0 ? userConfig.staleTime : DEFAULT_STALE_TIME;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get a cached entry if it exists and is not stale
|
|
31
|
+
*/
|
|
32
|
+
function getCachedPayload(pageContext) {
|
|
33
|
+
if (typeof window === "undefined") return null;
|
|
34
|
+
const staleTime = getStaleTime(pageContext);
|
|
35
|
+
if (staleTime === 0) return null;
|
|
36
|
+
const globalState = getGlobalClientState();
|
|
37
|
+
const cacheKey = getCacheKey(pageContext);
|
|
38
|
+
const cachedEntry = globalState.rscCache.get(cacheKey);
|
|
39
|
+
if (cachedEntry && Date.now() - cachedEntry.timestamp < staleTime) {
|
|
40
|
+
console.log("[RSC Cache] Using cached payload for", cacheKey);
|
|
41
|
+
return cachedEntry.payload;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Store a payload in the cache
|
|
47
|
+
*/
|
|
48
|
+
function cachePayload(pageContext, payload) {
|
|
49
|
+
if (typeof window === "undefined") return;
|
|
50
|
+
const staleTime = getStaleTime(pageContext);
|
|
51
|
+
if (staleTime === 0) return;
|
|
52
|
+
const globalState = getGlobalClientState();
|
|
53
|
+
const cacheKey = getCacheKey(pageContext);
|
|
54
|
+
globalState.rscCache.set(cacheKey, {
|
|
55
|
+
payload,
|
|
56
|
+
timestamp: Date.now()
|
|
57
|
+
});
|
|
58
|
+
console.log("[RSC Cache] Stored payload for", cacheKey);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Invalidate the cache entry for a specific page
|
|
62
|
+
*/
|
|
63
|
+
function invalidateCache(pageContext) {
|
|
64
|
+
if (typeof window === "undefined") return;
|
|
65
|
+
const globalState = getGlobalClientState();
|
|
66
|
+
const cacheKey = getCacheKey(pageContext);
|
|
67
|
+
if (globalState.rscCache.has(cacheKey)) {
|
|
68
|
+
globalState.rscCache.delete(cacheKey);
|
|
69
|
+
console.log("[RSC Cache] Invalidated main cache for", cacheKey);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Mark all server component cache entries as stale
|
|
74
|
+
* This is useful when a server action changes data that server components depend on
|
|
75
|
+
*/
|
|
76
|
+
function invalidateServerComponentCache() {
|
|
77
|
+
if (typeof window === "undefined") return;
|
|
78
|
+
const globalState = getGlobalClientState();
|
|
79
|
+
if (globalState.serverComponentCache.size > 0) {
|
|
80
|
+
let staleCount = 0;
|
|
81
|
+
globalState.serverComponentCache.forEach((entry) => {
|
|
82
|
+
if (!entry.isStale) {
|
|
83
|
+
entry.isStale = true;
|
|
84
|
+
staleCount++;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
if (staleCount > 0) console.log(`[RSC Cache] Marked ${staleCount} server component cache entries as stale`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Clear all pending server component requests
|
|
92
|
+
* This is useful when navigating between pages or when invalidating the cache
|
|
93
|
+
*/
|
|
94
|
+
function clearPendingServerComponentRequests() {
|
|
95
|
+
if (typeof window === "undefined") return;
|
|
96
|
+
const globalState = getGlobalClientState();
|
|
97
|
+
globalState.pendingRequests.clear();
|
|
98
|
+
console.log("[RSC Cache] Cleared pending server component requests");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get a cached server component if it exists
|
|
102
|
+
* Returns the component even if it's stale (stale-while-revalidate pattern)
|
|
103
|
+
* The caller should check the isStale flag and trigger a revalidation if needed
|
|
104
|
+
*/
|
|
105
|
+
function getCachedServerComponent(key, pageContext) {
|
|
106
|
+
if (typeof window === "undefined") return {
|
|
107
|
+
component: null,
|
|
108
|
+
isStale: false
|
|
109
|
+
};
|
|
110
|
+
const staleTime = getStaleTime(pageContext);
|
|
111
|
+
const globalState = getGlobalClientState();
|
|
112
|
+
const cachedEntry = globalState.serverComponentCache.get(key);
|
|
113
|
+
if (staleTime === 0) return {
|
|
114
|
+
component: null,
|
|
115
|
+
isStale: false
|
|
116
|
+
};
|
|
117
|
+
if (!cachedEntry) return {
|
|
118
|
+
component: null,
|
|
119
|
+
isStale: false
|
|
120
|
+
};
|
|
121
|
+
const componentName = key.split("-")[0];
|
|
122
|
+
const isExplicitlyStale = cachedEntry.isStale === true;
|
|
123
|
+
const isTimeStale = Date.now() - cachedEntry.timestamp >= staleTime;
|
|
124
|
+
const isStale = isExplicitlyStale || isTimeStale;
|
|
125
|
+
if (isStale) console.log(`[RSC Cache] Using stale server component: ${componentName}`);
|
|
126
|
+
else console.log(`[RSC Cache] Using fresh server component: ${componentName}`);
|
|
127
|
+
return {
|
|
128
|
+
component: cachedEntry.payload.returnValue,
|
|
129
|
+
isStale
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Mark a server component as being revalidated
|
|
134
|
+
*/
|
|
135
|
+
function markServerComponentRevalidating(key) {
|
|
136
|
+
if (typeof window === "undefined") return;
|
|
137
|
+
const globalState = getGlobalClientState();
|
|
138
|
+
const cachedEntry = globalState.serverComponentCache.get(key);
|
|
139
|
+
if (cachedEntry) {
|
|
140
|
+
cachedEntry.revalidating = true;
|
|
141
|
+
const componentName = key.split("-")[0];
|
|
142
|
+
console.log(`[RSC Cache] Revalidating server component: ${componentName}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Store a server component in the cache
|
|
147
|
+
*/
|
|
148
|
+
function cacheServerComponent(key, component, pageContext) {
|
|
149
|
+
if (typeof window === "undefined") return;
|
|
150
|
+
const staleTime = getStaleTime(pageContext);
|
|
151
|
+
if (staleTime === 0) return;
|
|
152
|
+
const globalState = getGlobalClientState();
|
|
153
|
+
globalState.serverComponentCache.set(key, {
|
|
154
|
+
payload: { returnValue: component },
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
isStale: false,
|
|
157
|
+
revalidating: false
|
|
158
|
+
});
|
|
159
|
+
const componentName = key.split("-")[0];
|
|
160
|
+
console.log(`[RSC Cache] Stored fresh server component: ${componentName}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
export { cachePayload, cacheServerComponent, clearPendingServerComponentRequests, getCachedPayload, getCachedServerComponent, getGlobalClientState, invalidateCache, invalidateServerComponentCache, markServerComponentRevalidating };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { cachePayload, clearPendingServerComponentRequests, getCachedPayload, getGlobalClientState, invalidateCache, invalidateServerComponentCache } from "./cache-BCYpxG4P.js";
|
|
2
|
+
import { startTransition } from "react";
|
|
3
|
+
import envName from "virtual:enviroment-name";
|
|
4
|
+
import { tinyassert } from "@hiogawa/utils";
|
|
5
|
+
import * as ReactClient from "@vitejs/plugin-rsc/react/browser";
|
|
6
|
+
|
|
7
|
+
//#region src/runtime/client.tsx
|
|
8
|
+
tinyassert(envName === "client", "Invalid environment");
|
|
9
|
+
function getVikeUrlOriginal(pageContext) {
|
|
10
|
+
return `${pageContext.urlPathname === "/" ? "" : pageContext.urlPathname}/index.pageContext.json${pageContext.urlParsed.searchOriginal || ""}`;
|
|
11
|
+
}
|
|
12
|
+
async function callServer(id, args) {
|
|
13
|
+
const globalState = getGlobalClientState();
|
|
14
|
+
const isRscCall = globalState.isRscCall;
|
|
15
|
+
console.log("[RSC Client] Calling server action:", id, isRscCall ? "(from server component)" : "");
|
|
16
|
+
const result = await ReactClient.createFromFetch(fetch("/_rsc", {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: {
|
|
19
|
+
"x-rsc-action": id,
|
|
20
|
+
"x-vike-urloriginal": getVikeUrlOriginal(globalState.pageContext),
|
|
21
|
+
...isRscCall ? { "x-rsc-component-call": "true" } : {}
|
|
22
|
+
},
|
|
23
|
+
body: await ReactClient.encodeReply(args)
|
|
24
|
+
}));
|
|
25
|
+
if (result.root) {
|
|
26
|
+
console.log("[RSC Client] Server action triggered re-render");
|
|
27
|
+
startTransition(() => {
|
|
28
|
+
globalState.setPayload?.((current) => {
|
|
29
|
+
cachePayload(current.pageContext, result);
|
|
30
|
+
return {
|
|
31
|
+
pageContext: current.pageContext,
|
|
32
|
+
payload: result
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
console.log("[RSC Client] Server action returned without re-render");
|
|
38
|
+
if (!isRscCall && typeof window !== "undefined") {
|
|
39
|
+
if (globalState.pageContext) invalidateCache(globalState.pageContext);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!isRscCall) invalidateServerComponentCache();
|
|
43
|
+
return result.returnValue;
|
|
44
|
+
}
|
|
45
|
+
ReactClient.setServerCallback(callServer);
|
|
46
|
+
if (import.meta.hot) import.meta.hot.on("rsc:update", async () => {
|
|
47
|
+
const globalState = getGlobalClientState();
|
|
48
|
+
invalidateCache(getGlobalClientState().pageContext);
|
|
49
|
+
invalidateServerComponentCache();
|
|
50
|
+
const payload = await onNavigate(globalState.pageContext);
|
|
51
|
+
globalState.setPayload?.((current) => {
|
|
52
|
+
return {
|
|
53
|
+
pageContext: current.pageContext,
|
|
54
|
+
payload
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
function onNavigate(pageContext) {
|
|
59
|
+
console.log("[RSC Client] Navigation:", pageContext.urlPathname);
|
|
60
|
+
const globalState = getGlobalClientState();
|
|
61
|
+
clearPendingServerComponentRequests();
|
|
62
|
+
const cachedPayload = getCachedPayload(pageContext);
|
|
63
|
+
if (cachedPayload) {
|
|
64
|
+
globalState.navigationPromise = Promise.resolve(cachedPayload);
|
|
65
|
+
return Promise.resolve(cachedPayload);
|
|
66
|
+
}
|
|
67
|
+
console.log("[RSC Client] Fetching RSC payload for", pageContext.urlPathname);
|
|
68
|
+
const fetchPromise = ReactClient.createFromFetch(fetch("/_rsc", {
|
|
69
|
+
method: "GET",
|
|
70
|
+
headers: { "x-vike-urloriginal": getVikeUrlOriginal(pageContext) }
|
|
71
|
+
}));
|
|
72
|
+
globalState.navigationPromise = fetchPromise;
|
|
73
|
+
fetchPromise.then((payload) => {
|
|
74
|
+
cachePayload(pageContext, payload);
|
|
75
|
+
});
|
|
76
|
+
return fetchPromise;
|
|
77
|
+
}
|
|
78
|
+
async function parseRscStream(stream) {
|
|
79
|
+
console.log("[RSC Client] Parsing RSC stream...");
|
|
80
|
+
const initialPayload = await ReactClient.createFromReadableStream(stream);
|
|
81
|
+
console.log("[RSC Client] RSC stream parsed");
|
|
82
|
+
return initialPayload;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { onNavigate, parseRscStream };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { rsc } from "./runtime/rscBridge.js";
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import "./getGlobalObject-CzWO6NfD.js";
|
|
2
|
+
import { usePageContext } from "./pageContext-client-CmvZ4bmk.js";
|
|
3
|
+
import { cacheServerComponent, getCachedServerComponent, getGlobalClientState, markServerComponentRevalidating } from "./cache-BCYpxG4P.js";
|
|
4
|
+
import React, { useEffect } from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/runtime/rscBridge.tsx
|
|
8
|
+
function rsc(c) {
|
|
9
|
+
return (props) => {
|
|
10
|
+
const pageContext = usePageContext();
|
|
11
|
+
const { fallback,...rest } = props;
|
|
12
|
+
const Loading = pageContext.config.Loading?.component || (() => null);
|
|
13
|
+
const fallback_ = fallback ?? /* @__PURE__ */ jsx(Loading, {});
|
|
14
|
+
const cacheKey = `${c.name}-${JSON.stringify(rest)}`;
|
|
15
|
+
const { component: cachedComponent, isStale } = getCachedServerComponent(cacheKey, pageContext);
|
|
16
|
+
const [comp, setComp] = React.useState(cachedComponent);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const globalState = getGlobalClientState();
|
|
19
|
+
const fetchOrRevalidate = () => {
|
|
20
|
+
const pendingRequest = globalState.pendingRequests.get(cacheKey);
|
|
21
|
+
if (pendingRequest) {
|
|
22
|
+
console.log(`[RSC Client] Reusing pending request for ${c.name || "UnknownComponent"}`, rest);
|
|
23
|
+
pendingRequest.then((result) => {
|
|
24
|
+
setComp(result);
|
|
25
|
+
});
|
|
26
|
+
} else {
|
|
27
|
+
console.log(`[RSC Client] ${cachedComponent ? "Revalidating" : "Fetching"} server component ${c.name || "UnknownComponent"}`, rest);
|
|
28
|
+
if (cachedComponent) markServerComponentRevalidating(cacheKey);
|
|
29
|
+
globalState.isRscCall = true;
|
|
30
|
+
const serverComponentPromise = c(rest);
|
|
31
|
+
globalState.isRscCall = false;
|
|
32
|
+
const requestPromise = serverComponentPromise.then((result) => {
|
|
33
|
+
cacheServerComponent(cacheKey, result, pageContext);
|
|
34
|
+
globalState.pendingRequests.delete(cacheKey);
|
|
35
|
+
return result;
|
|
36
|
+
}).catch((error) => {
|
|
37
|
+
console.error("[RSC Client] Error fetching server component:", error);
|
|
38
|
+
globalState.pendingRequests.delete(cacheKey);
|
|
39
|
+
throw error;
|
|
40
|
+
});
|
|
41
|
+
globalState.pendingRequests.set(cacheKey, requestPromise);
|
|
42
|
+
requestPromise.then(setComp);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
if (!cachedComponent || isStale) fetchOrRevalidate();
|
|
46
|
+
}, []);
|
|
47
|
+
if (!comp) return fallback_;
|
|
48
|
+
return comp;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { rsc };
|
package/dist/config.d.ts
ADDED