183 lines
6.6 KiB
Plaintext
183 lines
6.6 KiB
Plaintext
const require_utils = require("../utils.cjs");
|
|
const require_invariant = require("../invariant.cjs");
|
|
const require_not_found = require("../not-found.cjs");
|
|
const require_ssr_match_id = require("./ssr-match-id.cjs");
|
|
//#region src/ssr/ssr-client.ts
|
|
function hydrateMatch(match, deyhydratedMatch) {
|
|
match.id = deyhydratedMatch.i;
|
|
match.__beforeLoadContext = deyhydratedMatch.b;
|
|
match.loaderData = deyhydratedMatch.l;
|
|
match.status = deyhydratedMatch.s;
|
|
match.ssr = deyhydratedMatch.ssr;
|
|
match.updatedAt = deyhydratedMatch.u;
|
|
match.error = deyhydratedMatch.e;
|
|
if (deyhydratedMatch.g !== void 0) match.globalNotFound = deyhydratedMatch.g;
|
|
}
|
|
async function hydrate(router) {
|
|
if (!window.$_TSR) {
|
|
if (process.env.NODE_ENV !== "production") throw new Error("Invariant failed: Expected to find bootstrap data on window.$_TSR, but we did not. Please file an issue!");
|
|
require_invariant.invariant();
|
|
}
|
|
const serializationAdapters = router.options.serializationAdapters;
|
|
if (serializationAdapters?.length) {
|
|
const fromSerializableMap = /* @__PURE__ */ new Map();
|
|
serializationAdapters.forEach((adapter) => {
|
|
fromSerializableMap.set(adapter.key, adapter.fromSerializable);
|
|
});
|
|
window.$_TSR.t = fromSerializableMap;
|
|
window.$_TSR.buffer.forEach((script) => script());
|
|
}
|
|
window.$_TSR.initialized = true;
|
|
if (!window.$_TSR.router) {
|
|
if (process.env.NODE_ENV !== "production") throw new Error("Invariant failed: Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!");
|
|
require_invariant.invariant();
|
|
}
|
|
const dehydratedRouter = window.$_TSR.router;
|
|
dehydratedRouter.matches.forEach((dehydratedMatch) => {
|
|
dehydratedMatch.i = require_ssr_match_id.hydrateSsrMatchId(dehydratedMatch.i);
|
|
});
|
|
if (dehydratedRouter.lastMatchId) dehydratedRouter.lastMatchId = require_ssr_match_id.hydrateSsrMatchId(dehydratedRouter.lastMatchId);
|
|
const { manifest, dehydratedData, lastMatchId } = dehydratedRouter;
|
|
router.ssr = { manifest };
|
|
const nonce = document.querySelector("meta[property=\"csp-nonce\"]")?.content;
|
|
router.options.ssr = { nonce };
|
|
const matches = router.matchRoutes(router.stores.location.get());
|
|
const routeChunkPromise = Promise.all(matches.map((match) => router.loadRouteChunk(router.looseRoutesById[match.routeId])));
|
|
function setMatchForcePending(match) {
|
|
const pendingMinMs = router.looseRoutesById[match.routeId].options.pendingMinMs ?? router.options.defaultPendingMinMs;
|
|
if (pendingMinMs) {
|
|
const minPendingPromise = require_utils.createControlledPromise();
|
|
match._nonReactive.minPendingPromise = minPendingPromise;
|
|
match._forcePending = true;
|
|
setTimeout(() => {
|
|
minPendingPromise.resolve();
|
|
router.updateMatch(match.id, (prev) => {
|
|
prev._nonReactive.minPendingPromise = void 0;
|
|
return {
|
|
...prev,
|
|
_forcePending: void 0
|
|
};
|
|
});
|
|
}, pendingMinMs);
|
|
}
|
|
}
|
|
function setRouteSsr(match) {
|
|
const route = router.looseRoutesById[match.routeId];
|
|
if (route) route.options.ssr = match.ssr;
|
|
}
|
|
let firstNonSsrMatchIndex = void 0;
|
|
matches.forEach((match) => {
|
|
const dehydratedMatch = dehydratedRouter.matches.find((d) => d.i === match.id);
|
|
if (!dehydratedMatch) {
|
|
match._nonReactive.dehydrated = false;
|
|
match.ssr = false;
|
|
setRouteSsr(match);
|
|
return;
|
|
}
|
|
hydrateMatch(match, dehydratedMatch);
|
|
setRouteSsr(match);
|
|
match._nonReactive.dehydrated = match.ssr !== false;
|
|
if (match.ssr === "data-only" || match.ssr === false) {
|
|
if (firstNonSsrMatchIndex === void 0) {
|
|
firstNonSsrMatchIndex = match.index;
|
|
setMatchForcePending(match);
|
|
}
|
|
}
|
|
});
|
|
router.stores.setMatches(matches);
|
|
await router.options.hydrate?.(dehydratedData);
|
|
const activeMatches = router.stores.matches.get();
|
|
const location = router.stores.location.get();
|
|
await Promise.all(activeMatches.map(async (match) => {
|
|
try {
|
|
const route = router.looseRoutesById[match.routeId];
|
|
const parentContext = activeMatches[match.index - 1]?.context ?? router.options.context;
|
|
if (route.options.context) {
|
|
const contextFnContext = {
|
|
deps: match.loaderDeps,
|
|
params: match.params,
|
|
context: parentContext ?? {},
|
|
location,
|
|
navigate: (opts) => router.navigate({
|
|
...opts,
|
|
_fromLocation: location
|
|
}),
|
|
buildLocation: router.buildLocation,
|
|
cause: match.cause,
|
|
abortController: match.abortController,
|
|
preload: false,
|
|
matches,
|
|
routeId: route.id
|
|
};
|
|
match.__routeContext = route.options.context(contextFnContext) ?? void 0;
|
|
}
|
|
match.context = {
|
|
...parentContext,
|
|
...match.__routeContext,
|
|
...match.__beforeLoadContext
|
|
};
|
|
const assetContext = {
|
|
ssr: router.options.ssr,
|
|
matches: activeMatches,
|
|
match,
|
|
params: match.params,
|
|
loaderData: match.loaderData
|
|
};
|
|
const headFnContent = await route.options.head?.(assetContext);
|
|
const scripts = await route.options.scripts?.(assetContext);
|
|
match.meta = headFnContent?.meta;
|
|
match.links = headFnContent?.links;
|
|
match.headScripts = headFnContent?.scripts;
|
|
match.styles = headFnContent?.styles;
|
|
match.scripts = scripts;
|
|
} catch (err) {
|
|
if (require_not_found.isNotFound(err)) {
|
|
match.error = { isNotFound: true };
|
|
console.error(`NotFound error during hydration for routeId: ${match.routeId}`, err);
|
|
} else {
|
|
match.error = err;
|
|
console.error(`Error during hydration for route ${match.routeId}:`, err);
|
|
throw err;
|
|
}
|
|
}
|
|
}));
|
|
const isSpaMode = matches[matches.length - 1].id !== lastMatchId;
|
|
if (!matches.some((m) => m.ssr === false) && !isSpaMode) {
|
|
matches.forEach((match) => {
|
|
match._nonReactive.dehydrated = void 0;
|
|
});
|
|
router.stores.resolvedLocation.set(router.stores.location.get());
|
|
return routeChunkPromise;
|
|
}
|
|
const loadPromise = Promise.resolve().then(() => router.load()).catch((err) => {
|
|
console.error("Error during router hydration:", err);
|
|
});
|
|
if (isSpaMode) {
|
|
const match = matches[1];
|
|
if (!match) {
|
|
if (process.env.NODE_ENV !== "production") throw new Error("Invariant failed: Expected to find a match below the root match in SPA mode.");
|
|
require_invariant.invariant();
|
|
}
|
|
setMatchForcePending(match);
|
|
match._displayPending = true;
|
|
match._nonReactive.displayPendingPromise = loadPromise;
|
|
loadPromise.then(() => {
|
|
router.batch(() => {
|
|
if (router.stores.status.get() === "pending") {
|
|
router.stores.status.set("idle");
|
|
router.stores.resolvedLocation.set(router.stores.location.get());
|
|
}
|
|
router.updateMatch(match.id, (prev) => ({
|
|
...prev,
|
|
_displayPending: void 0,
|
|
displayPendingPromise: void 0
|
|
}));
|
|
});
|
|
});
|
|
}
|
|
return routeChunkPromise;
|
|
}
|
|
//#endregion
|
|
exports.hydrate = hydrate;
|
|
|
|
//# sourceMappingURL=ssr-client.cjs.map |