waku 0.20.2-alpha.1 → 0.20.2
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/client.d.ts +6 -3
- package/dist/client.js +31 -10
- package/dist/lib/middleware/dev-server.js +1 -5
- package/dist/lib/renderers/dev-worker-impl.js +4 -11
- package/dist/lib/renderers/rsc-renderer.d.ts +0 -1
- package/dist/lib/renderers/rsc-renderer.js +1 -1
- package/dist/lib/utils/path.js +1 -1
- package/dist/router/client.js +20 -3
- package/package.json +4 -7
- package/src/client.ts +36 -12
- package/src/lib/middleware/dev-server.ts +1 -7
- package/src/lib/renderers/dev-worker-impl.ts +6 -18
- package/src/lib/renderers/rsc-renderer.ts +3 -6
- package/src/lib/utils/path.ts +1 -1
- package/src/router/client.ts +36 -3
package/dist/client.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ declare global {
|
|
|
5
5
|
readonly env: Record<string, string>;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
type Elements = Promise<Record<string, ReactNode
|
|
9
|
-
|
|
8
|
+
type Elements = Promise<Record<string, ReactNode>> & {
|
|
9
|
+
prev?: Record<string, ReactNode> | undefined;
|
|
10
|
+
};
|
|
11
|
+
type SetElements = (updater: (prev: Elements) => Elements) => void;
|
|
10
12
|
type CacheEntry = [
|
|
11
13
|
input: string,
|
|
12
14
|
searchParamsString: string,
|
|
@@ -24,10 +26,11 @@ export declare const Root: ({ initialInput, initialSearchParamsString, cache, un
|
|
|
24
26
|
children: ReactNode;
|
|
25
27
|
}) => import("react").FunctionComponentElement<import("react").ProviderProps<(input: string, searchParams?: URLSearchParams) => void>>;
|
|
26
28
|
export declare const useRefetch: () => (input: string, searchParams?: URLSearchParams) => void;
|
|
27
|
-
export declare const Slot: ({ id, children, fallback, }: {
|
|
29
|
+
export declare const Slot: ({ id, children, fallback, unstable_shouldRenderPrev, }: {
|
|
28
30
|
id: string;
|
|
29
31
|
children?: ReactNode;
|
|
30
32
|
fallback?: ReactNode;
|
|
33
|
+
unstable_shouldRenderPrev?: (err: unknown) => boolean;
|
|
31
34
|
}) => string | number | bigint | true | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | Promise<import("react").AwaitedReactNode> | import("react").FunctionComponentElement<import("react").ProviderProps<ReactNode>>;
|
|
32
35
|
export declare const Children: () => ReactNode;
|
|
33
36
|
/**
|
package/dist/client.js
CHANGED
|
@@ -17,13 +17,30 @@ const checkStatus = async (responsePromise)=>{
|
|
|
17
17
|
const getCached = (c, m, k)=>(m.has(k) ? m : m.set(k, c())).get(k);
|
|
18
18
|
const cache1 = new WeakMap();
|
|
19
19
|
const mergeElements = (a, b)=>{
|
|
20
|
-
const getResult =
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
const getResult = ()=>{
|
|
21
|
+
const promise = new Promise((resolve, reject)=>{
|
|
22
|
+
Promise.all([
|
|
23
|
+
a,
|
|
24
|
+
b
|
|
25
|
+
]).then(([a, b])=>{
|
|
26
|
+
const nextElements = {
|
|
27
|
+
...a,
|
|
28
|
+
...b
|
|
29
|
+
};
|
|
30
|
+
delete nextElements._value;
|
|
31
|
+
promise.prev = a;
|
|
32
|
+
resolve(nextElements);
|
|
33
|
+
}).catch((e)=>{
|
|
34
|
+
a.then((a)=>{
|
|
35
|
+
promise.prev = a;
|
|
36
|
+
reject(e);
|
|
37
|
+
}, ()=>{
|
|
38
|
+
promise.prev = a.prev;
|
|
39
|
+
reject(e);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
return promise;
|
|
27
44
|
};
|
|
28
45
|
const cache2 = getCached(()=>new WeakMap(), cache1, a);
|
|
29
46
|
return getCached(getResult, cache2, b);
|
|
@@ -96,7 +113,7 @@ export const Root = ({ initialInput, initialSearchParamsString, cache, unstable_
|
|
|
96
113
|
export const useRefetch = ()=>use(RefetchContext);
|
|
97
114
|
const ChildrenContext = createContext(undefined);
|
|
98
115
|
const ChildrenContextProvider = memo(ChildrenContext.Provider);
|
|
99
|
-
export const Slot = ({ id, children, fallback })=>{
|
|
116
|
+
export const Slot = ({ id, children, fallback, unstable_shouldRenderPrev })=>{
|
|
100
117
|
const elementsPromise = use(ElementsContext);
|
|
101
118
|
if (!elementsPromise) {
|
|
102
119
|
throw new Error('Missing Root component');
|
|
@@ -105,12 +122,16 @@ export const Slot = ({ id, children, fallback })=>{
|
|
|
105
122
|
try {
|
|
106
123
|
elements = use(elementsPromise);
|
|
107
124
|
} catch (e) {
|
|
108
|
-
if (e instanceof Error) {
|
|
125
|
+
if (e instanceof Error && !('statusCode' in e)) {
|
|
109
126
|
// HACK we assume any error as Not Found,
|
|
110
127
|
// probably caused by history api fallback
|
|
111
128
|
e.statusCode = 404;
|
|
112
129
|
}
|
|
113
|
-
|
|
130
|
+
if (unstable_shouldRenderPrev?.(e) && elementsPromise.prev) {
|
|
131
|
+
elements = elementsPromise.prev;
|
|
132
|
+
} else {
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
114
135
|
}
|
|
115
136
|
if (!(id in elements)) {
|
|
116
137
|
if (fallback) {
|
|
@@ -5,7 +5,7 @@ import { Server } from 'node:http';
|
|
|
5
5
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
6
6
|
import { createServer as createViteServer } from 'vite';
|
|
7
7
|
import viteReact from '@vitejs/plugin-react';
|
|
8
|
-
import { joinPath, fileURLToFilePath, encodeFilePathToAbsolute } from '../utils/path.js';
|
|
8
|
+
import { joinPath, fileURLToFilePath, encodeFilePathToAbsolute, decodeFilePathFromAbsolute } from '../utils/path.js';
|
|
9
9
|
import { deepFreeze, hasStatusCode } from './utils.js';
|
|
10
10
|
import { renderRsc, getSsrConfig } from './rsc-renderer.js';
|
|
11
11
|
import { nonjsResolvePlugin } from '../plugins/vite-plugin-nonjs-resolve.js';
|
|
@@ -29,12 +29,12 @@ const configSrcDir = getEnvironmentData('CONFIG_SRC_DIR');
|
|
|
29
29
|
const configEntries = getEnvironmentData('CONFIG_ENTRIES');
|
|
30
30
|
const configPrivateDir = getEnvironmentData('CONFIG_PRIVATE_DIR');
|
|
31
31
|
const resolveClientEntryForDev = (id, config, initialModules)=>{
|
|
32
|
+
let file = id.startsWith('file://') ? decodeFilePathFromAbsolute(fileURLToFilePath(id)) : id;
|
|
32
33
|
for (const moduleNode of initialModules){
|
|
33
|
-
if (moduleNode.file ===
|
|
34
|
+
if (moduleNode.file === file) {
|
|
34
35
|
return moduleNode.url;
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
let file = id.startsWith('file://') ? fileURLToFilePath(id) : id;
|
|
38
38
|
if (file.startsWith(config.rootDir)) {
|
|
39
39
|
file = file.slice(config.rootDir.length + 1); // '+ 1' to remove '/'
|
|
40
40
|
} else {
|
|
@@ -69,7 +69,6 @@ const handleRender = async (mesg)=>{
|
|
|
69
69
|
}, {
|
|
70
70
|
isDev: true,
|
|
71
71
|
loadServerFile,
|
|
72
|
-
loadServerModule,
|
|
73
72
|
resolveClientEntry: (id)=>resolveClientEntryForDev(id, {
|
|
74
73
|
rootDir: vite.config.root,
|
|
75
74
|
basePath: rest.config.basePath
|
|
@@ -191,9 +190,7 @@ const mergedViteConfig = await mergeUserViteConfig({
|
|
|
191
190
|
'workerd'
|
|
192
191
|
]
|
|
193
192
|
},
|
|
194
|
-
external: [
|
|
195
|
-
// FIXME We want to externalize waku, but it fails on windows.
|
|
196
|
-
noExternal: [
|
|
193
|
+
external: [
|
|
197
194
|
'waku'
|
|
198
195
|
]
|
|
199
196
|
},
|
|
@@ -214,10 +211,6 @@ const loadServerFile = async (fileURL)=>{
|
|
|
214
211
|
const vite = await vitePromise;
|
|
215
212
|
return vite.ssrLoadModule(fileURLToFilePath(fileURL));
|
|
216
213
|
};
|
|
217
|
-
const loadServerModule = async (id)=>{
|
|
218
|
-
const vite = await vitePromise;
|
|
219
|
-
return vite.ssrLoadModule(id);
|
|
220
|
-
};
|
|
221
214
|
const loadEntries = async (config)=>{
|
|
222
215
|
const vite = await vitePromise;
|
|
223
216
|
const filePath = joinPath(vite.config.root, config.srcDir, configEntries);
|
|
@@ -21,7 +21,6 @@ type RenderRscOpts = {
|
|
|
21
21
|
isDev: true;
|
|
22
22
|
entries: EntriesDev;
|
|
23
23
|
loadServerFile: (fileURL: string) => Promise<unknown>;
|
|
24
|
-
loadServerModule: (id: string) => Promise<unknown>;
|
|
25
24
|
resolveClientEntry: (id: string) => string;
|
|
26
25
|
};
|
|
27
26
|
export declare function renderRsc(args: RenderRscArgs, opts: RenderRscOpts): Promise<ReadableStream>;
|
|
@@ -20,7 +20,7 @@ export async function renderRsc(args, opts) {
|
|
|
20
20
|
const loadServerModule = (key)=>isDev ? import(/* @vite-ignore */ SERVER_MODULE_MAP[key]) : loadModule(key);
|
|
21
21
|
const [{ default: { renderToReadableStream, decodeReply } }, { runWithRenderStore }] = await Promise.all([
|
|
22
22
|
loadServerModule('rsdw-server'),
|
|
23
|
-
|
|
23
|
+
loadServerModule('waku-server')
|
|
24
24
|
]);
|
|
25
25
|
const bundlerConfig = new Proxy({}, {
|
|
26
26
|
get (_target, encodedId) {
|
package/dist/lib/utils/path.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
const ABSOLUTE_WIN32_PATH_REGEXP = /^\/[a-zA-Z]:\//;
|
|
9
9
|
export const encodeFilePathToAbsolute = (filePath)=>{
|
|
10
10
|
if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {
|
|
11
|
-
throw new Error('Unsupported absolute file path');
|
|
11
|
+
throw new Error('Unsupported absolute file path: ' + filePath);
|
|
12
12
|
}
|
|
13
13
|
if (filePath.startsWith('/')) {
|
|
14
14
|
return filePath;
|
package/dist/router/client.js
CHANGED
|
@@ -193,7 +193,21 @@ const equalRouteProps = (a, b)=>{
|
|
|
193
193
|
}
|
|
194
194
|
return true;
|
|
195
195
|
};
|
|
196
|
-
|
|
196
|
+
const RouterSlot = ({ route, routerData, cachedRef, id, fallback, children })=>{
|
|
197
|
+
const unstable_shouldRenderPrev = (_err)=>{
|
|
198
|
+
const shouldSkip = routerData[0];
|
|
199
|
+
const skip = getSkipList(shouldSkip, [
|
|
200
|
+
id
|
|
201
|
+
], route, cachedRef.current);
|
|
202
|
+
return skip.length > 0;
|
|
203
|
+
};
|
|
204
|
+
return createElement(Slot, {
|
|
205
|
+
id,
|
|
206
|
+
fallback,
|
|
207
|
+
unstable_shouldRenderPrev
|
|
208
|
+
}, children);
|
|
209
|
+
};
|
|
210
|
+
const InnerRouter = ({ routerData })=>{
|
|
197
211
|
const refetch = useRefetch();
|
|
198
212
|
const [route, setRoute] = useState(()=>parseRoute(new URL(window.location.href)));
|
|
199
213
|
const componentIds = getComponentIds(route.path);
|
|
@@ -314,7 +328,10 @@ function InnerRouter({ routerData }) {
|
|
|
314
328
|
behavior: state?.waku_new_path ? 'instant' : 'auto'
|
|
315
329
|
});
|
|
316
330
|
});
|
|
317
|
-
const children = componentIds.reduceRight((acc, id)=>createElement(
|
|
331
|
+
const children = componentIds.reduceRight((acc, id)=>createElement(RouterSlot, {
|
|
332
|
+
route,
|
|
333
|
+
routerData,
|
|
334
|
+
cachedRef,
|
|
318
335
|
id,
|
|
319
336
|
fallback: acc
|
|
320
337
|
}, acc), null);
|
|
@@ -325,7 +342,7 @@ function InnerRouter({ routerData }) {
|
|
|
325
342
|
prefetchRoute
|
|
326
343
|
}
|
|
327
344
|
}, children);
|
|
328
|
-
}
|
|
345
|
+
};
|
|
329
346
|
const DEFAULT_ROUTER_DATA = [];
|
|
330
347
|
export function Router({ routerData = DEFAULT_ROUTER_DATA }) {
|
|
331
348
|
const route = parseRoute(new URL(window.location.href));
|
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waku",
|
|
3
3
|
"description": "⛩️ The minimal React framework",
|
|
4
|
-
"version": "0.20.2
|
|
5
|
-
"publishConfig": {
|
|
6
|
-
"tag": "next"
|
|
7
|
-
},
|
|
4
|
+
"version": "0.20.2",
|
|
8
5
|
"type": "module",
|
|
9
6
|
"author": "Daishi Kato",
|
|
10
7
|
"homepage": "https://waku.gg",
|
|
@@ -86,9 +83,9 @@
|
|
|
86
83
|
"vitest": "^1.6.0"
|
|
87
84
|
},
|
|
88
85
|
"peerDependencies": {
|
|
89
|
-
"react": "19.0.0-beta-
|
|
90
|
-
"react-dom": "19.0.0-beta-
|
|
91
|
-
"react-server-dom-webpack": "19.0.0-beta-
|
|
86
|
+
"react": "19.0.0-beta-e7d213dfb0-20240507",
|
|
87
|
+
"react-dom": "19.0.0-beta-e7d213dfb0-20240507",
|
|
88
|
+
"react-server-dom-webpack": "19.0.0-beta-e7d213dfb0-20240507"
|
|
92
89
|
},
|
|
93
90
|
"scripts": {
|
|
94
91
|
"dev": "swc src -d dist -w --strip-leading-paths",
|
package/src/client.ts
CHANGED
|
@@ -39,25 +39,43 @@ const checkStatus = async (
|
|
|
39
39
|
return response;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
type Elements = Promise<Record<string, ReactNode
|
|
42
|
+
type Elements = Promise<Record<string, ReactNode>> & {
|
|
43
|
+
prev?: Record<string, ReactNode> | undefined;
|
|
44
|
+
};
|
|
43
45
|
|
|
44
46
|
const getCached = <T>(c: () => T, m: WeakMap<object, T>, k: object): T =>
|
|
45
47
|
(m.has(k) ? m : m.set(k, c())).get(k) as T;
|
|
46
48
|
const cache1 = new WeakMap();
|
|
47
|
-
const mergeElements = (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
const mergeElements = (a: Elements, b: Elements): Elements => {
|
|
50
|
+
const getResult = () => {
|
|
51
|
+
const promise: Elements = new Promise((resolve, reject) => {
|
|
52
|
+
Promise.all([a, b])
|
|
53
|
+
.then(([a, b]) => {
|
|
54
|
+
const nextElements = { ...a, ...b };
|
|
55
|
+
delete nextElements._value;
|
|
56
|
+
promise.prev = a;
|
|
57
|
+
resolve(nextElements);
|
|
58
|
+
})
|
|
59
|
+
.catch((e) => {
|
|
60
|
+
a.then(
|
|
61
|
+
(a) => {
|
|
62
|
+
promise.prev = a;
|
|
63
|
+
reject(e);
|
|
64
|
+
},
|
|
65
|
+
() => {
|
|
66
|
+
promise.prev = a.prev;
|
|
67
|
+
reject(e);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return promise;
|
|
55
73
|
};
|
|
56
74
|
const cache2 = getCached(() => new WeakMap(), cache1, a);
|
|
57
75
|
return getCached(getResult, cache2, b);
|
|
58
76
|
};
|
|
59
77
|
|
|
60
|
-
type SetElements = (updater:
|
|
78
|
+
type SetElements = (updater: (prev: Elements) => Elements) => void;
|
|
61
79
|
type CacheEntry = [
|
|
62
80
|
input: string,
|
|
63
81
|
searchParamsString: string,
|
|
@@ -191,10 +209,12 @@ export const Slot = ({
|
|
|
191
209
|
id,
|
|
192
210
|
children,
|
|
193
211
|
fallback,
|
|
212
|
+
unstable_shouldRenderPrev,
|
|
194
213
|
}: {
|
|
195
214
|
id: string;
|
|
196
215
|
children?: ReactNode;
|
|
197
216
|
fallback?: ReactNode;
|
|
217
|
+
unstable_shouldRenderPrev?: (err: unknown) => boolean;
|
|
198
218
|
}) => {
|
|
199
219
|
const elementsPromise = use(ElementsContext);
|
|
200
220
|
if (!elementsPromise) {
|
|
@@ -204,12 +224,16 @@ export const Slot = ({
|
|
|
204
224
|
try {
|
|
205
225
|
elements = use(elementsPromise);
|
|
206
226
|
} catch (e) {
|
|
207
|
-
if (e instanceof Error) {
|
|
227
|
+
if (e instanceof Error && !('statusCode' in e)) {
|
|
208
228
|
// HACK we assume any error as Not Found,
|
|
209
229
|
// probably caused by history api fallback
|
|
210
230
|
(e as any).statusCode = 404;
|
|
211
231
|
}
|
|
212
|
-
|
|
232
|
+
if (unstable_shouldRenderPrev?.(e) && elementsPromise.prev) {
|
|
233
|
+
elements = elementsPromise.prev;
|
|
234
|
+
} else {
|
|
235
|
+
throw e;
|
|
236
|
+
}
|
|
213
237
|
}
|
|
214
238
|
if (!(id in elements)) {
|
|
215
239
|
if (fallback) {
|
|
@@ -97,13 +97,7 @@ export const devServer: Middleware = (options) => {
|
|
|
97
97
|
],
|
|
98
98
|
},
|
|
99
99
|
ssr: {
|
|
100
|
-
external: [
|
|
101
|
-
'waku',
|
|
102
|
-
'waku/client',
|
|
103
|
-
'waku/server',
|
|
104
|
-
'waku/router/client',
|
|
105
|
-
'waku/router/server',
|
|
106
|
-
],
|
|
100
|
+
external: ['waku'],
|
|
107
101
|
},
|
|
108
102
|
server: { middlewareMode: true },
|
|
109
103
|
});
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
joinPath,
|
|
14
14
|
fileURLToFilePath,
|
|
15
15
|
encodeFilePathToAbsolute,
|
|
16
|
+
decodeFilePathFromAbsolute,
|
|
16
17
|
} from '../utils/path.js';
|
|
17
18
|
import { deepFreeze, hasStatusCode } from './utils.js';
|
|
18
19
|
import type { MessageReq, MessageRes } from './dev-worker-api.js';
|
|
@@ -50,12 +51,14 @@ const resolveClientEntryForDev = (
|
|
|
50
51
|
config: { rootDir: string; basePath: string },
|
|
51
52
|
initialModules: ClonableModuleNode[],
|
|
52
53
|
) => {
|
|
54
|
+
let file = id.startsWith('file://')
|
|
55
|
+
? decodeFilePathFromAbsolute(fileURLToFilePath(id))
|
|
56
|
+
: id;
|
|
53
57
|
for (const moduleNode of initialModules) {
|
|
54
|
-
if (moduleNode.file ===
|
|
58
|
+
if (moduleNode.file === file) {
|
|
55
59
|
return moduleNode.url;
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
|
-
let file = id.startsWith('file://') ? fileURLToFilePath(id) : id;
|
|
59
62
|
if (file.startsWith(config.rootDir)) {
|
|
60
63
|
file = file.slice(config.rootDir.length + 1); // '+ 1' to remove '/'
|
|
61
64
|
} else {
|
|
@@ -95,7 +98,6 @@ const handleRender = async (mesg: MessageReq & { type: 'render' }) => {
|
|
|
95
98
|
{
|
|
96
99
|
isDev: true,
|
|
97
100
|
loadServerFile,
|
|
98
|
-
loadServerModule,
|
|
99
101
|
resolveClientEntry: (id: string) =>
|
|
100
102
|
resolveClientEntryForDev(
|
|
101
103
|
id,
|
|
@@ -201,16 +203,7 @@ const mergedViteConfig = await mergeUserViteConfig({
|
|
|
201
203
|
conditions: ['react-server', 'workerd'],
|
|
202
204
|
externalConditions: ['react-server', 'workerd'],
|
|
203
205
|
},
|
|
204
|
-
external: [
|
|
205
|
-
// FIXME We want to externalize waku, but it fails on windows.
|
|
206
|
-
// 'waku',
|
|
207
|
-
// 'waku/client',
|
|
208
|
-
// 'waku/server',
|
|
209
|
-
// 'waku/router/client',
|
|
210
|
-
// 'waku/router/server',
|
|
211
|
-
],
|
|
212
|
-
// FIXME We want to externalize waku, but it fails on windows.
|
|
213
|
-
noExternal: ['waku'],
|
|
206
|
+
external: ['waku'],
|
|
214
207
|
},
|
|
215
208
|
appType: 'custom',
|
|
216
209
|
server: { middlewareMode: true, hmr: { server: dummyServer } },
|
|
@@ -227,11 +220,6 @@ const loadServerFile = async (fileURL: string) => {
|
|
|
227
220
|
return vite.ssrLoadModule(fileURLToFilePath(fileURL));
|
|
228
221
|
};
|
|
229
222
|
|
|
230
|
-
const loadServerModule = async (id: string) => {
|
|
231
|
-
const vite = await vitePromise;
|
|
232
|
-
return vite.ssrLoadModule(id);
|
|
233
|
-
};
|
|
234
|
-
|
|
235
223
|
const loadEntries = async (config: { srcDir: string }) => {
|
|
236
224
|
const vite = await vitePromise;
|
|
237
225
|
const filePath = joinPath(vite.config.root, config.srcDir, configEntries);
|
|
@@ -41,7 +41,6 @@ type RenderRscOpts =
|
|
|
41
41
|
isDev: true;
|
|
42
42
|
entries: EntriesDev;
|
|
43
43
|
loadServerFile: (fileURL: string) => Promise<unknown>;
|
|
44
|
-
loadServerModule: (id: string) => Promise<unknown>;
|
|
45
44
|
resolveClientEntry: (id: string) => string;
|
|
46
45
|
};
|
|
47
46
|
|
|
@@ -85,11 +84,9 @@ export async function renderRsc(
|
|
|
85
84
|
{ runWithRenderStore },
|
|
86
85
|
] = await Promise.all([
|
|
87
86
|
loadServerModule<{ default: typeof RSDWServerType }>('rsdw-server'),
|
|
88
|
-
(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
runWithRenderStore: typeof runWithRenderStoreType;
|
|
92
|
-
}>,
|
|
87
|
+
loadServerModule<{ runWithRenderStore: typeof runWithRenderStoreType }>(
|
|
88
|
+
'waku-server',
|
|
89
|
+
),
|
|
93
90
|
]);
|
|
94
91
|
|
|
95
92
|
const bundlerConfig = new Proxy(
|
package/src/lib/utils/path.ts
CHANGED
|
@@ -10,7 +10,7 @@ const ABSOLUTE_WIN32_PATH_REGEXP = /^\/[a-zA-Z]:\//;
|
|
|
10
10
|
|
|
11
11
|
export const encodeFilePathToAbsolute = (filePath: string) => {
|
|
12
12
|
if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {
|
|
13
|
-
throw new Error('Unsupported absolute file path');
|
|
13
|
+
throw new Error('Unsupported absolute file path: ' + filePath);
|
|
14
14
|
}
|
|
15
15
|
if (filePath.startsWith('/')) {
|
|
16
16
|
return filePath;
|
package/src/router/client.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import type {
|
|
16
16
|
ComponentProps,
|
|
17
17
|
FunctionComponent,
|
|
18
|
+
MutableRefObject,
|
|
18
19
|
ReactNode,
|
|
19
20
|
AnchorHTMLAttributes,
|
|
20
21
|
ReactElement,
|
|
@@ -286,7 +287,34 @@ const equalRouteProps = (a: RouteProps, b: RouteProps) => {
|
|
|
286
287
|
return true;
|
|
287
288
|
};
|
|
288
289
|
|
|
289
|
-
|
|
290
|
+
const RouterSlot = ({
|
|
291
|
+
route,
|
|
292
|
+
routerData,
|
|
293
|
+
cachedRef,
|
|
294
|
+
id,
|
|
295
|
+
fallback,
|
|
296
|
+
children,
|
|
297
|
+
}: {
|
|
298
|
+
route: RouteProps;
|
|
299
|
+
routerData: RouterData;
|
|
300
|
+
cachedRef: MutableRefObject<Record<string, RouteProps>>;
|
|
301
|
+
id: string;
|
|
302
|
+
fallback?: ReactNode;
|
|
303
|
+
children?: ReactNode;
|
|
304
|
+
}) => {
|
|
305
|
+
const unstable_shouldRenderPrev = (_err: unknown) => {
|
|
306
|
+
const shouldSkip = routerData[0];
|
|
307
|
+
const skip = getSkipList(shouldSkip, [id], route, cachedRef.current);
|
|
308
|
+
return skip.length > 0;
|
|
309
|
+
};
|
|
310
|
+
return createElement(
|
|
311
|
+
Slot,
|
|
312
|
+
{ id, fallback, unstable_shouldRenderPrev },
|
|
313
|
+
children,
|
|
314
|
+
);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const InnerRouter = ({ routerData }: { routerData: RouterData }) => {
|
|
290
318
|
const refetch = useRefetch();
|
|
291
319
|
|
|
292
320
|
const [route, setRoute] = useState(() =>
|
|
@@ -418,7 +446,12 @@ function InnerRouter({ routerData }: { routerData: RouterData }) {
|
|
|
418
446
|
});
|
|
419
447
|
|
|
420
448
|
const children = componentIds.reduceRight(
|
|
421
|
-
(acc: ReactNode, id) =>
|
|
449
|
+
(acc: ReactNode, id) =>
|
|
450
|
+
createElement(
|
|
451
|
+
RouterSlot,
|
|
452
|
+
{ route, routerData, cachedRef, id, fallback: acc },
|
|
453
|
+
acc,
|
|
454
|
+
),
|
|
422
455
|
null,
|
|
423
456
|
);
|
|
424
457
|
|
|
@@ -427,7 +460,7 @@ function InnerRouter({ routerData }: { routerData: RouterData }) {
|
|
|
427
460
|
{ value: { route, changeRoute, prefetchRoute } },
|
|
428
461
|
children,
|
|
429
462
|
);
|
|
430
|
-
}
|
|
463
|
+
};
|
|
431
464
|
|
|
432
465
|
// Note: The router data must be a stable mutable object (array).
|
|
433
466
|
type RouterData = [
|