akanjs 3.0.0-beta.25 → 3.0.0-beta.27
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/client/csrTypes.ts +2 -0
- package/client/device.ts +9 -9
- package/common/Logger.ts +26 -2
- package/common/RouteLayering.ts +52 -0
- package/common/hmrPhase.ts +2 -0
- package/common/index.ts +1 -0
- package/package.json +1 -1
- package/server/artifact/devBuildRecovery.ts +12 -0
- package/server/artifact/index.ts +1 -0
- package/server/artifact/ipcTypes.ts +2 -0
- package/server/di/diLifecycle.ts +1 -1
- package/server/hmr/clientScript.ts +18 -5
- package/server/hmr/csrDevRuntime.ts +11 -7
- package/server/hmr/csrDevShell.ts +26 -5
- package/server/hmr/devArtifactPruner.ts +77 -0
- package/server/hmr/devHmrController.ts +69 -44
- package/server/hmr/ssrDevShim.ts +7 -1
- package/server/routeTreeBuilder.ts +14 -39
- package/server/rscWorker.tsx +7 -1
- package/server/rscWorkerHost.ts +126 -40
- package/server/webRouter.ts +25 -19
- package/types/client/csrTypes.d.ts +2 -0
- package/types/common/RouteLayering.d.ts +28 -0
- package/types/common/hmrPhase.d.ts +2 -0
- package/types/common/index.d.ts +1 -0
- package/types/server/artifact/devBuildRecovery.d.ts +4 -0
- package/types/server/artifact/index.d.ts +1 -0
- package/types/server/artifact/ipcTypes.d.ts +2 -0
- package/types/server/hmr/devArtifactPruner.d.ts +9 -0
- package/types/server/hmr/devHmrController.d.ts +0 -2
- package/types/server/rscWorkerHost.d.ts +5 -4
- package/types/server/webRouter.d.ts +4 -2
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +3 -1
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeBridge.kt +19 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeShell.swift +12 -2
- package/vendor/@akanjs/native/packages/core/src/runtime.ts +26 -5
- package/vendor/@akanjs/native/packages/desktop/src/host.ts +5 -3
- package/webkit/CsrRouteTable.ts +15 -35
- package/webkit/bootCsr.tsx +11 -8
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Logger } from "akanjs/common";
|
|
4
|
+
import { CrossSiteGuard } from "../../signal/CrossSiteGuard";
|
|
4
5
|
import {
|
|
5
6
|
BuilderRpc,
|
|
6
7
|
type ClientManifest,
|
|
8
|
+
DevBuildRecovery,
|
|
7
9
|
type DevBuildStatus,
|
|
8
10
|
type HmrTrace,
|
|
9
11
|
RouteClientCache,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
import type { RscReloadFailure, RscWorker } from "../rscWorkerHost";
|
|
14
16
|
import type { RenderState } from "../types";
|
|
15
17
|
import { CSR_DEV_DIRNAME, CSR_DEV_MANIFEST_FILE, type CsrDevManifest, SSR_DEV_DIRNAME } from "./csrDevManifest";
|
|
18
|
+
import { DevArtifactPruner } from "./devArtifactPruner";
|
|
16
19
|
import { isAkanRuntimeMetadataFile } from "./runtimeMetadataFile";
|
|
17
20
|
import { type SsrUpdateMessage, SsrUpdateQueue } from "./ssrUpdateQueue";
|
|
18
21
|
import { type ChangeKind, type HmrMessage, type HmrWsData, HmrWsHub } from "./wsHub";
|
|
@@ -49,11 +52,7 @@ export function devBuildStatusToHmrMessage(
|
|
|
49
52
|
files: status.files.length,
|
|
50
53
|
};
|
|
51
54
|
}
|
|
52
|
-
if (!previous
|
|
53
|
-
|
|
54
|
-
const sameGeneration = status.phase === "backend" || status.phase === "scan" || status.phase === "route";
|
|
55
|
-
const recovered = sameGeneration ? status.generation >= previous.generation : status.generation > previous.generation;
|
|
56
|
-
if (!recovered) return null;
|
|
55
|
+
if (!DevBuildRecovery.recovers(previous, status)) return null;
|
|
57
56
|
return {
|
|
58
57
|
type: "build-status",
|
|
59
58
|
status: "ok",
|
|
@@ -85,6 +84,8 @@ export class DevHmrController {
|
|
|
85
84
|
readonly #ssrUpdates = new SsrUpdateQueue((message) => this.#sendSsrUpdate(message));
|
|
86
85
|
readonly #builderRpc: BuilderRpc;
|
|
87
86
|
readonly routeCache: RouteClientCache;
|
|
87
|
+
#recheckingRoute = false;
|
|
88
|
+
#recheckAgain: DevBuildStatus | null = null;
|
|
88
89
|
readonly #recentClientEntries = new Set<string>();
|
|
89
90
|
/** File to the newest save that invalidated its routes already: that save's pages build must not drop them again. */
|
|
90
91
|
readonly #earlyInvalidated = new Map<string, number>();
|
|
@@ -97,10 +98,12 @@ export class DevHmrController {
|
|
|
97
98
|
readonly #buildStatusByPhase = new Map<DevBuildStatus["phase"], DevBuildStatus>();
|
|
98
99
|
#graphSeeds: string[];
|
|
99
100
|
#runningBundlePath: string | null;
|
|
101
|
+
readonly #pruner: DevArtifactPruner;
|
|
100
102
|
|
|
101
103
|
constructor({ artifactDir, renderState, rsc, seedIndex, upgradeHmrWs, pagesBundlePath }: DevHmrControllerOptions) {
|
|
102
104
|
this.#artifactDir = artifactDir;
|
|
103
105
|
this.#runningBundlePath = pagesBundlePath ? path.resolve(pagesBundlePath) : null;
|
|
106
|
+
this.#pruner = new DevArtifactPruner(artifactDir);
|
|
104
107
|
this.#renderState = renderState;
|
|
105
108
|
this.#rsc = rsc;
|
|
106
109
|
this.#seedIndex = seedIndex;
|
|
@@ -155,28 +158,17 @@ export class DevHmrController {
|
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
handleWs(req: Request): Response | undefined {
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
CrossSiteGuard.assertOrigin(req, new URL(req.url), "hmr");
|
|
164
|
+
} catch {
|
|
165
|
+
return new Response("Forbidden", { status: 403 });
|
|
166
|
+
}
|
|
158
167
|
const client = new URL(req.url).searchParams.get("client") === "csr" ? "csr" : "ssr";
|
|
159
168
|
if (this.#upgradeHmrWs(req, { kind: "akan-hmr", openedAt: Date.now(), client })) return;
|
|
160
169
|
return new Response("Failed to upgrade HMR WebSocket", { status: 500 });
|
|
161
170
|
}
|
|
162
171
|
|
|
163
|
-
async ensureRoute(url: URL) {
|
|
164
|
-
const started = Date.now();
|
|
165
|
-
const matched =
|
|
166
|
-
RouteSeedIndexStore.match(url.pathname, this.#seedIndex.entries) ??
|
|
167
|
-
RouteSeedIndexStore.matchPrefix(url.pathname, this.#seedIndex.entries);
|
|
168
|
-
if (matched) await this.routeCache.ensure(matched.entry.routeId, matched.entry.seeds);
|
|
169
|
-
this.#logger.verbose(
|
|
170
|
-
`[route-cache] ensure pathname=${url.pathname} routeId=${matched?.entry.routeId ?? "(none)"} in ${Date.now() - started}ms`,
|
|
171
|
-
);
|
|
172
|
-
return this.routeCache.snapshot();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
routeIdsForPath(pathname: string): string[] | undefined {
|
|
176
|
-
const matched = RouteSeedIndexStore.match(pathname, this.#seedIndex.entries);
|
|
177
|
-
return matched ? [matched.entry.routeId] : undefined;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
172
|
#sendSsrUpdate(message: SsrUpdateMessage): void {
|
|
181
173
|
this.#renderState.ssrGeneration = message.generation;
|
|
182
174
|
this.#hub.broadcast({ ...message, trace: DevHmrController.#broadcastTrace(message.trace) });
|
|
@@ -235,6 +227,7 @@ export class DevHmrController {
|
|
|
235
227
|
this.#renderState.cssBytesByUrl = cssBytesByUrl;
|
|
236
228
|
this.#rsc.updateCssAssets(this.#renderState.cssAssets);
|
|
237
229
|
this.#hub.broadcast({ type: "css-update", cssAssets: this.#renderState.cssAssets });
|
|
230
|
+
void this.#pruner.pruneStyles(this.#renderState.cssAssets);
|
|
238
231
|
this.#logger.verbose(
|
|
239
232
|
`css-update assets=${Object.keys(this.#renderState.cssAssets).length} generation=${css.generation ?? "(unknown)"} files=${css.changedFiles?.length ?? 0} in ${Date.now() - started}ms (ipc)`,
|
|
240
233
|
);
|
|
@@ -266,6 +259,7 @@ export class DevHmrController {
|
|
|
266
259
|
const manifest = this.routeCache.snapshot();
|
|
267
260
|
|
|
268
261
|
const running = bundlePath ? path.resolve(bundlePath) : null;
|
|
262
|
+
let tabBuildId = buildId;
|
|
269
263
|
if (serverTouched === false && !clearAll && running === this.#runningBundlePath) {
|
|
270
264
|
this.#logger.verbose(
|
|
271
265
|
`[SSR] pages bundle unchanged for the server; buildId ${this.#renderState.buildId} kept`,
|
|
@@ -275,25 +269,29 @@ export class DevHmrController {
|
|
|
275
269
|
this.#renderState.buildId = buildId;
|
|
276
270
|
const reloadStarted = Date.now();
|
|
277
271
|
try {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
272
|
+
const adopted = await this.#rsc.reload({
|
|
273
|
+
clientManifest: manifest.clientManifest,
|
|
274
|
+
cssAssets: this.#renderState.cssAssets,
|
|
275
|
+
buildId,
|
|
276
|
+
pagesBundlePath: bundlePath,
|
|
277
|
+
});
|
|
278
|
+
this.#adoptBundle(adopted.pagesBundlePath);
|
|
279
|
+
|
|
280
|
+
tabBuildId = adopted.buildId;
|
|
286
281
|
} catch (error) {
|
|
287
282
|
const failure = DevHmrController.#reloadFailure(error);
|
|
288
283
|
|
|
289
284
|
if (failure) {
|
|
290
285
|
this.#renderState.buildId = failure.adopted.buildId;
|
|
291
|
-
this.#
|
|
286
|
+
this.#adoptBundle(failure.adopted.pagesBundlePath);
|
|
292
287
|
} else if (this.#renderState.buildId === buildId) this.#renderState.buildId = previousBuildId;
|
|
293
288
|
|
|
294
|
-
if (failure?.
|
|
295
|
-
|
|
296
|
-
|
|
289
|
+
if (failure?.adopted.buildId !== buildId) {
|
|
290
|
+
|
|
291
|
+
if (failure && failure.failed.buildId !== buildId) this.#ssrUpdates.release(generation);
|
|
292
|
+
else this.#failPagesReload(generation, files, error);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
297
295
|
}
|
|
298
296
|
this.#logger.verbose(`[SSR] rsc reload buildId=${buildId} in ${Date.now() - reloadStarted}ms`);
|
|
299
297
|
}
|
|
@@ -301,7 +299,7 @@ export class DevHmrController {
|
|
|
301
299
|
const broadcastTrace = DevHmrController.#broadcastTrace(trace);
|
|
302
300
|
if (shouldReload) this.#ssrUpdates.clear(generation);
|
|
303
301
|
const released = shouldReload ? { released: 0, reload: false } : this.#ssrUpdates.release(generation);
|
|
304
|
-
if (shouldReload) this.#hub.broadcast({ type: "reload", buildId });
|
|
302
|
+
if (shouldReload) this.#hub.broadcast({ type: "reload", buildId: tabBuildId });
|
|
305
303
|
else if (released.reload)
|
|
306
304
|
this.#logger.verbose(`[hmr] generation=${generation} released a registry reload; no RSC refresh needed`);
|
|
307
305
|
else if (serverTouched === false)
|
|
@@ -311,7 +309,7 @@ export class DevHmrController {
|
|
|
311
309
|
else
|
|
312
310
|
this.#hub.broadcast({
|
|
313
311
|
type: "rsc-refresh",
|
|
314
|
-
buildId,
|
|
312
|
+
buildId: tabBuildId,
|
|
315
313
|
generation,
|
|
316
314
|
changedFiles,
|
|
317
315
|
routeIds,
|
|
@@ -324,6 +322,13 @@ export class DevHmrController {
|
|
|
324
322
|
});
|
|
325
323
|
}
|
|
326
324
|
|
|
325
|
+
#adoptBundle(bundlePath: string): void {
|
|
326
|
+
const running = path.resolve(bundlePath);
|
|
327
|
+
if (running === this.#runningBundlePath) return;
|
|
328
|
+
this.#runningBundlePath = running;
|
|
329
|
+
void this.#pruner.prunePages(running);
|
|
330
|
+
}
|
|
331
|
+
|
|
327
332
|
static #reloadFailure(error: unknown): RscReloadFailure | null {
|
|
328
333
|
return error instanceof Error && "adopted" in error ? (error as RscReloadFailure) : null;
|
|
329
334
|
}
|
|
@@ -351,6 +356,7 @@ export class DevHmrController {
|
|
|
351
356
|
}
|
|
352
357
|
|
|
353
358
|
#recordBuildStatus(status: DevBuildStatus): void {
|
|
359
|
+
this.#recheckFailedRoute(status);
|
|
354
360
|
const previous = this.#buildStatusByPhase.get(status.phase);
|
|
355
361
|
const message = devBuildStatusToHmrMessage(status, previous);
|
|
356
362
|
|
|
@@ -363,6 +369,26 @@ export class DevHmrController {
|
|
|
363
369
|
);
|
|
364
370
|
}
|
|
365
371
|
|
|
372
|
+
#recheckFailedRoute(status: DevBuildStatus, { again = false }: { again?: boolean } = {}): void {
|
|
373
|
+
if (!status.ok || (status.phase !== "pages" && status.phase !== "ssr")) return;
|
|
374
|
+
if (this.#recheckingRoute) {
|
|
375
|
+
this.#recheckAgain = status;
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const failed = this.#buildStatusByPhase.get("route");
|
|
379
|
+
if (!failed || failed.ok || !failed.scope || (!again && failed.generation >= status.generation)) return;
|
|
380
|
+
this.#recheckingRoute = true;
|
|
381
|
+
void this.routeCache
|
|
382
|
+
.ensure(failed.scope, failed.files)
|
|
383
|
+
.catch(() => undefined)
|
|
384
|
+
.finally(() => {
|
|
385
|
+
this.#recheckingRoute = false;
|
|
386
|
+
const next = this.#recheckAgain;
|
|
387
|
+
this.#recheckAgain = null;
|
|
388
|
+
if (next) this.#recheckFailedRoute(next, { again: true });
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
366
392
|
#createRouteCache() {
|
|
367
393
|
return new RouteClientCache({
|
|
368
394
|
buildRoute: async (routeId, { seeds, knownEntries, generation }) => {
|
|
@@ -387,17 +413,16 @@ export class DevHmrController {
|
|
|
387
413
|
if (delta.newEntries.length === 0 && removedEntries.size === 0) return;
|
|
388
414
|
this.#rememberClientDeps(routeId, delta.clientDeps, delta.clientDepsByEntry);
|
|
389
415
|
try {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
);
|
|
416
|
+
const adopted = await this.#rsc.reload({
|
|
417
|
+
clientManifest: nextMerged.clientManifest,
|
|
418
|
+
cssAssets: this.#renderState.cssAssets,
|
|
419
|
+
buildId: this.#renderState.buildId,
|
|
420
|
+
});
|
|
421
|
+
this.#adoptBundle(adopted.pagesBundlePath);
|
|
397
422
|
} catch (error) {
|
|
398
423
|
|
|
399
424
|
const failure = DevHmrController.#reloadFailure(error);
|
|
400
|
-
if (failure) this.#
|
|
425
|
+
if (failure) this.#adoptBundle(failure.adopted.pagesBundlePath);
|
|
401
426
|
this.#logger.warn(`[SSR] route ${routeId} merged, but the worker did not reload: ${String(error)}`);
|
|
402
427
|
}
|
|
403
428
|
this.#logger.verbose(
|
package/server/hmr/ssrDevShim.ts
CHANGED
|
@@ -52,9 +52,15 @@ export class SsrDevShim {
|
|
|
52
52
|
var hello = self.__AKAN_SSR_HELLO_GENERATION__;
|
|
53
53
|
if (typeof hello === "number") self.__akan.catchUp(hello, c.prefix);
|
|
54
54
|
}
|
|
55
|
+
function runtime(attempt) {
|
|
56
|
+
return script(c.runtime).catch(function (error) {
|
|
57
|
+
if (attempt >= 3) throw error;
|
|
58
|
+
return wait(500).then(state).then(function () { return runtime(attempt + 1); });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
55
61
|
function boot() {
|
|
56
62
|
if (!booting)
|
|
57
|
-
booting = self.__AKAN_SSR_BOOT__ =
|
|
63
|
+
booting = self.__AKAN_SSR_BOOT__ = runtime(0).then(function () {
|
|
58
64
|
var early = self.__AKAN_SSR_EARLY_UPDATES__ || [];
|
|
59
65
|
self.__AKAN_SSR_EARLY_UPDATES__ = null;
|
|
60
66
|
for (var i = 0; i < early.length; i++) self.__akan.hot(early[i]);
|
|
@@ -15,8 +15,9 @@ import {
|
|
|
15
15
|
getRouteExports,
|
|
16
16
|
Logger,
|
|
17
17
|
matchRoutePattern,
|
|
18
|
-
parseBasePaths,
|
|
19
18
|
parseRouteModuleKey,
|
|
19
|
+
type RouteLayer,
|
|
20
|
+
RouteLayering,
|
|
20
21
|
routeSegmentToTreePath,
|
|
21
22
|
} from "akanjs/common";
|
|
22
23
|
import { createElement } from "react";
|
|
@@ -54,15 +55,12 @@ export class RouteTreeBuilder {
|
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
readonly #context: PagesContext;
|
|
57
|
-
readonly #baseLayoutPaths: string[];
|
|
58
58
|
readonly #routeMap = new Map<string, Route>();
|
|
59
59
|
readonly #pagePatterns: { key: string; pattern: string }[] = [];
|
|
60
60
|
readonly #fallbackRoutes: LayoutFallbackRoute[] = [];
|
|
61
61
|
|
|
62
62
|
constructor(context: PagesContext) {
|
|
63
63
|
this.#context = context;
|
|
64
|
-
const basePaths = process.env.AKAN_PUBLIC_BASE_PATHS ? parseBasePaths(process.env.AKAN_PUBLIC_BASE_PATHS) : null;
|
|
65
|
-
this.#baseLayoutPaths = ["/", "/:lang", ...(basePaths?.map((bp) => `/:lang/${bp}`) ?? [])];
|
|
66
64
|
this.#routeMap.set("/", { path: "/", children: new Map() });
|
|
67
65
|
}
|
|
68
66
|
|
|
@@ -169,7 +167,7 @@ export class RouteTreeBuilder {
|
|
|
169
167
|
targetRouteMap.set(targetPath, {
|
|
170
168
|
...(targetRouteMap.get(targetPath) ?? { path: targetPath, children: new Map<string, Route>() }),
|
|
171
169
|
...(parsed.kind === "layout"
|
|
172
|
-
? { renderLayout: routeRender }
|
|
170
|
+
? { renderLayout: routeRender, isRootLayout: parsed.isInternalRootLayout }
|
|
173
171
|
: {
|
|
174
172
|
renderPage: routeRender,
|
|
175
173
|
pageIncludesOwnLayout: parsed.leaf === "_index",
|
|
@@ -178,48 +176,27 @@ export class RouteTreeBuilder {
|
|
|
178
176
|
} as Route);
|
|
179
177
|
}
|
|
180
178
|
|
|
181
|
-
#getPathRoutes(
|
|
182
|
-
route
|
|
183
|
-
parentRootLayouts: RouteRender[] = [],
|
|
184
|
-
parentLayouts: RouteRender[] = [],
|
|
185
|
-
parentPaths: string[] = [],
|
|
186
|
-
parentHead?: ResolveHead,
|
|
187
|
-
parentRootRenders: RouteRender[] = [],
|
|
188
|
-
): PathRoute[] {
|
|
189
|
-
const parentPath = parentPaths.filter((p) => p !== "/").join("");
|
|
190
|
-
const currentPathSegment = /^\/\(.*\)$/.test(route.path) ? "" : route.path;
|
|
191
|
-
const isRoot = this.#baseLayoutPaths.includes(parentPath + currentPathSegment) && parentRootLayouts.length < 2;
|
|
192
|
-
const routePath = parentPath + currentPathSegment;
|
|
193
|
-
const pathSegments = [...parentPaths, ...(currentPathSegment ? [currentPathSegment] : [])];
|
|
194
|
-
const currentRootLayout = isRoot && route.renderLayout ? route.renderLayout : null;
|
|
195
|
-
|
|
196
|
-
const currentOverrideRenders = route.renderOverrides ? [route.renderOverrides] : [];
|
|
197
|
-
const nodeRenders = [...currentOverrideRenders, ...(route.renderLayout ? [route.renderLayout] : [])];
|
|
198
|
-
const rootLayoutStack = [...parentRootLayouts, ...(currentRootLayout ? [currentRootLayout] : [])];
|
|
199
|
-
const renderRootLayouts = isRoot ? [...parentRootRenders, ...nodeRenders] : parentRootRenders;
|
|
200
|
-
const renderLayouts = isRoot ? parentLayouts : [...parentLayouts, ...nodeRenders];
|
|
179
|
+
#getPathRoutes(route: Route, parent: RouteLayer<RouteRender> | null = null, parentHead?: ResolveHead): PathRoute[] {
|
|
180
|
+
const layer = RouteLayering.of(route, parent);
|
|
201
181
|
if (route.renderLayout) {
|
|
202
182
|
this.#fallbackRoutes.push({
|
|
203
|
-
path:
|
|
204
|
-
pathSegments,
|
|
205
|
-
renderRootLayouts,
|
|
206
|
-
renderLayouts,
|
|
183
|
+
path: layer.path,
|
|
184
|
+
pathSegments: layer.pathSegments,
|
|
185
|
+
renderRootLayouts: layer.renderRootLayouts,
|
|
186
|
+
renderLayouts: layer.renderLayouts,
|
|
207
187
|
});
|
|
208
188
|
}
|
|
209
189
|
const routeHead = RouteTreeBuilder.#composeHeadResolvers(route.renderLayout?.resolveHead, parentHead);
|
|
210
|
-
const pageNodeRenders = route.pageIncludesOwnLayout === false ? currentOverrideRenders : nodeRenders;
|
|
211
|
-
const pageRenderRootLayouts = isRoot ? [...parentRootRenders, ...pageNodeRenders] : parentRootRenders;
|
|
212
|
-
const pageRenderLayouts = isRoot ? parentLayouts : [...parentLayouts, ...pageNodeRenders];
|
|
213
190
|
const pageHead = route.pageIncludesOwnLayout === false ? parentHead : routeHead;
|
|
214
191
|
return [
|
|
215
192
|
...(route.renderPage
|
|
216
193
|
? [
|
|
217
194
|
{
|
|
218
|
-
path:
|
|
219
|
-
pathSegments,
|
|
195
|
+
path: layer.path,
|
|
196
|
+
pathSegments: layer.pathSegments,
|
|
220
197
|
renderPage: route.renderPage,
|
|
221
|
-
renderRootLayouts: pageRenderRootLayouts,
|
|
222
|
-
renderLayouts: pageRenderLayouts,
|
|
198
|
+
renderRootLayouts: layer.pageRenderRootLayouts,
|
|
199
|
+
renderLayouts: layer.pageRenderLayouts,
|
|
223
200
|
resolveHead: RouteTreeBuilder.#composeHeadResolvers(route.renderPage.resolveHead, pageHead),
|
|
224
201
|
isSpecialRoute: route.isSpecialRoute,
|
|
225
202
|
pageState: route.pageState ?? defaultPageState,
|
|
@@ -227,9 +204,7 @@ export class RouteTreeBuilder {
|
|
|
227
204
|
]
|
|
228
205
|
: []),
|
|
229
206
|
...(route.children.size
|
|
230
|
-
? [...route.children.values()].flatMap((child) =>
|
|
231
|
-
this.#getPathRoutes(child, rootLayoutStack, renderLayouts, pathSegments, routeHead, renderRootLayouts),
|
|
232
|
-
)
|
|
207
|
+
? [...route.children.values()].flatMap((child) => this.#getPathRoutes(child, layer, routeHead))
|
|
233
208
|
: []),
|
|
234
209
|
];
|
|
235
210
|
}
|
package/server/rscWorker.tsx
CHANGED
|
@@ -387,7 +387,12 @@ export class RscRenderer {
|
|
|
387
387
|
this.#resultCache.clear();
|
|
388
388
|
this.#patchResultCache.clear();
|
|
389
389
|
this.#logger.verbose(`reload complete buildId=${msg.buildId} in ${Date.now() - startedAt}ms`);
|
|
390
|
-
this.#send({
|
|
390
|
+
this.#send({
|
|
391
|
+
type: "reloaded",
|
|
392
|
+
buildId: msg.buildId,
|
|
393
|
+
reloadId: msg.reloadId,
|
|
394
|
+
pagesBundlePath: nextPagesBundlePath,
|
|
395
|
+
});
|
|
391
396
|
} catch (error) {
|
|
392
397
|
this.#logger.error(
|
|
393
398
|
`reload failed buildId=${msg.buildId}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`,
|
|
@@ -399,6 +404,7 @@ export class RscRenderer {
|
|
|
399
404
|
requestId: "__reload__",
|
|
400
405
|
buildId: msg.buildId,
|
|
401
406
|
reloadId: msg.reloadId,
|
|
407
|
+
running: { pagesBundlePath: this.#pagesBundlePath, buildId: this.#pagesBundleBuildId },
|
|
402
408
|
message: error instanceof Error ? error.message : String(error),
|
|
403
409
|
});
|
|
404
410
|
}
|