Initial boiler plate project

This commit is contained in:
2024-09-24 03:52:46 +00:00
parent 6120b2d6c3
commit 154b93e267
10034 changed files with 2079352 additions and 2 deletions

977
node_modules/next/dist/server/app-render/app-render.js generated vendored Normal file
View File

@ -0,0 +1,977 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "renderToHTMLOrFlight", {
enumerable: true,
get: function() {
return renderToHTMLOrFlight;
}
});
const _jsxruntime = require("react/jsx-runtime");
const _react = /*#__PURE__*/ _interop_require_default(require("react"));
const _renderresult = /*#__PURE__*/ _interop_require_default(require("../render-result"));
const _nodewebstreamshelper = require("../stream-utils/node-web-streams-helper");
const _matchsegments = require("../../client/components/match-segments");
const _internalutils = require("../internal-utils");
const _approuterheaders = require("../../client/components/app-router-headers");
const _metadata = require("../../lib/metadata/metadata");
const _requestasyncstoragewrapper = require("../async-storage/request-async-storage-wrapper");
const _staticgenerationasyncstoragewrapper = require("../async-storage/static-generation-async-storage-wrapper");
const _notfound = require("../../client/components/not-found");
const _redirect = require("../../client/components/redirect");
const _patchfetch = require("../lib/patch-fetch");
const _constants = require("../lib/trace/constants");
const _tracer = require("../lib/trace/tracer");
const _flightrenderresult = require("./flight-render-result");
const _createerrorhandler = require("./create-error-handler");
const _getshortdynamicparamtype = require("./get-short-dynamic-param-type");
const _getsegmentparam = require("./get-segment-param");
const _getscriptnoncefromheader = require("./get-script-nonce-from-header");
const _parseandvalidateflightrouterstate = require("./parse-and-validate-flight-router-state");
const _validateurl = require("./validate-url");
const _createflightrouterstatefromloadertree = require("./create-flight-router-state-from-loader-tree");
const _actionhandler = require("./action-handler");
const _bailouttocsr = require("../../shared/lib/lazy-dynamic/bailout-to-csr");
const _log = require("../../build/output/log");
const _requestcookies = require("../web/spec-extension/adapters/request-cookies");
const _serverinsertedhtml = require("./server-inserted-html");
const _requiredscripts = require("./required-scripts");
const _addpathprefix = require("../../shared/lib/router/utils/add-path-prefix");
const _makegetserverinsertedhtml = require("./make-get-server-inserted-html");
const _walktreewithflightrouterstate = require("./walk-tree-with-flight-router-state");
const _createcomponenttree = require("./create-component-tree");
const _getassetquerystring = require("./get-asset-query-string");
const _encryptionutils = require("./encryption-utils");
const _staticrenderer = require("./static/static-renderer");
const _hooksservercontext = require("../../client/components/hooks-server-context");
const _useflightresponse = require("./use-flight-response");
const _staticgenerationbailout = require("../../client/components/static-generation-bailout");
const _interceptionroutes = require("../future/helpers/interception-routes");
const _formatservererror = require("../../lib/format-server-error");
const _dynamicrendering = require("./dynamic-rendering");
const _clientcomponentrendererlogger = require("../client-component-renderer-logger");
const _actionutils = require("./action-utils");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function createNotFoundLoaderTree(loaderTree) {
// Align the segment with parallel-route-default in next-app-loader
return [
"",
{},
loaderTree[2]
];
}
/* This method is important for intercepted routes to function:
* when a route is intercepted, e.g. /blog/[slug], it will be rendered
* with the layout of the previous page, e.g. /profile/[id]. The problem is
* that the loader tree needs to know the dynamic param in order to render (id and slug in the example).
* Normally they are read from the path but since we are intercepting the route, the path would not contain id,
* so we need to read it from the router state.
*/ function findDynamicParamFromRouterState(flightRouterState, segment) {
if (!flightRouterState) {
return null;
}
const treeSegment = flightRouterState[0];
if ((0, _matchsegments.canSegmentBeOverridden)(segment, treeSegment)) {
if (!Array.isArray(treeSegment) || Array.isArray(segment)) {
return null;
}
return {
param: treeSegment[0],
value: treeSegment[1],
treeSegment: treeSegment,
type: treeSegment[2]
};
}
for (const parallelRouterState of Object.values(flightRouterState[1])){
const maybeDynamicParam = findDynamicParamFromRouterState(parallelRouterState, segment);
if (maybeDynamicParam) {
return maybeDynamicParam;
}
}
return null;
}
/**
* Returns a function that parses the dynamic segment and return the associated value.
*/ function makeGetDynamicParamFromSegment(params, flightRouterState) {
return function getDynamicParamFromSegment(// [slug] / [[slug]] / [...slug]
segment) {
const segmentParam = (0, _getsegmentparam.getSegmentParam)(segment);
if (!segmentParam) {
return null;
}
const key = segmentParam.param;
let value = params[key];
// this is a special marker that will be present for interception routes
if (value === "__NEXT_EMPTY_PARAM__") {
value = undefined;
}
if (Array.isArray(value)) {
value = value.map((i)=>encodeURIComponent(i));
} else if (typeof value === "string") {
value = encodeURIComponent(value);
}
if (!value) {
// Handle case where optional catchall does not have a value, e.g. `/dashboard/[...slug]` when requesting `/dashboard`
if (segmentParam.type === "optional-catchall") {
const type = _getshortdynamicparamtype.dynamicParamTypes[segmentParam.type];
return {
param: key,
value: null,
type: type,
// This value always has to be a string.
treeSegment: [
key,
"",
type
]
};
}
return findDynamicParamFromRouterState(flightRouterState, segment);
}
const type = (0, _getshortdynamicparamtype.getShortDynamicParamType)(segmentParam.type);
return {
param: key,
// The value that is passed to user code.
value: value,
// The value that is rendered in the router tree.
treeSegment: [
key,
Array.isArray(value) ? value.join("/") : value,
type
],
type: type
};
};
}
function NonIndex({ ctx }) {
const is404Page = ctx.pagePath === "/404";
const isInvalidStatusCode = typeof ctx.res.statusCode === "number" && ctx.res.statusCode > 400;
if (is404Page || isInvalidStatusCode) {
return /*#__PURE__*/ (0, _jsxruntime.jsx)("meta", {
name: "robots",
content: "noindex"
});
}
return null;
}
// Handle Flight render request. This is only used when client-side navigating. E.g. when you `router.push('/dashboard')` or `router.reload()`.
async function generateFlight(ctx, options) {
// Flight data that is going to be passed to the browser.
// Currently a single item array but in the future multiple patches might be combined in a single request.
let flightData = null;
const { componentMod: { tree: loaderTree, renderToReadableStream, createDynamicallyTrackedSearchParams }, getDynamicParamFromSegment, appUsingSizeAdjustment, staticGenerationStore: { urlPathname }, query, requestId, flightRouterState } = ctx;
if (!(options == null ? void 0 : options.skipFlight)) {
const [MetadataTree, MetadataOutlet] = (0, _metadata.createMetadataComponents)({
tree: loaderTree,
query,
metadataContext: (0, _metadata.createMetadataContext)(urlPathname, ctx.renderOpts),
getDynamicParamFromSegment,
appUsingSizeAdjustment,
createDynamicallyTrackedSearchParams
});
flightData = (await (0, _walktreewithflightrouterstate.walkTreeWithFlightRouterState)({
ctx,
createSegmentPath: (child)=>child,
loaderTreeToFilter: loaderTree,
parentParams: {},
flightRouterState,
isFirst: true,
// For flight, render metadata inside leaf page
// NOTE: in 14.2, fragment doesn't work well with React, using array instead
rscPayloadHead: [
/*#__PURE__*/ (0, _jsxruntime.jsx)(MetadataTree, {}, requestId),
/*#__PURE__*/ (0, _jsxruntime.jsx)(NonIndex, {
ctx: ctx
}, "noindex")
],
injectedCSS: new Set(),
injectedJS: new Set(),
injectedFontPreloadTags: new Set(),
rootLayoutIncluded: false,
asNotFound: ctx.isNotFoundPath || (options == null ? void 0 : options.asNotFound),
metadataOutlet: /*#__PURE__*/ (0, _jsxruntime.jsx)(MetadataOutlet, {})
})).map((path)=>path.slice(1)) // remove the '' (root) segment
;
}
const buildIdFlightDataPair = [
ctx.renderOpts.buildId,
flightData
];
// For app dir, use the bundled version of Flight server renderer (renderToReadableStream)
// which contains the subset React.
const flightReadableStream = renderToReadableStream(options ? [
options.actionResult,
buildIdFlightDataPair
] : buildIdFlightDataPair, ctx.clientReferenceManifest.clientModules, {
onError: ctx.flightDataRendererErrorHandler
});
return new _flightrenderresult.FlightRenderResult(flightReadableStream);
}
/**
* Creates a resolver that eagerly generates a flight payload that is then
* resolved when the resolver is called.
*/ function createFlightDataResolver(ctx) {
// Generate the flight data and as soon as it can, convert it into a string.
const promise = generateFlight(ctx).then(async (result)=>({
flightData: await result.toUnchunkedString(true)
}))// Otherwise if it errored, return the error.
.catch((err)=>({
err
}));
return async ()=>{
// Resolve the promise to get the flight data or error.
const result = await promise;
// If the flight data failed to render due to an error, re-throw the error
// here.
if ("err" in result) {
throw result.err;
}
// Otherwise, return the flight data.
return result.flightData;
};
}
/**
* Crawlers will inadvertently think the canonicalUrl in the RSC payload should be crawled
* when our intention is to just seed the router state with the current URL.
* This function splits up the pathname so that we can later join it on
* when we're ready to consume the path.
*/ function prepareInitialCanonicalUrl(pathname) {
return pathname.split("/");
}
// This is the root component that runs in the RSC context
async function ReactServerApp({ tree, ctx, asNotFound }) {
// Create full component tree from root to leaf.
const injectedCSS = new Set();
const injectedJS = new Set();
const injectedFontPreloadTags = new Set();
const missingSlots = new Set();
const { getDynamicParamFromSegment, query, appUsingSizeAdjustment, componentMod: { AppRouter, GlobalError, createDynamicallyTrackedSearchParams }, staticGenerationStore: { urlPathname } } = ctx;
const initialTree = (0, _createflightrouterstatefromloadertree.createFlightRouterStateFromLoaderTree)(tree, getDynamicParamFromSegment, query);
const [MetadataTree, MetadataOutlet] = (0, _metadata.createMetadataComponents)({
tree,
errorType: asNotFound ? "not-found" : undefined,
query,
metadataContext: (0, _metadata.createMetadataContext)(urlPathname, ctx.renderOpts),
getDynamicParamFromSegment: getDynamicParamFromSegment,
appUsingSizeAdjustment: appUsingSizeAdjustment,
createDynamicallyTrackedSearchParams
});
const seedData = await (0, _createcomponenttree.createComponentTree)({
ctx,
createSegmentPath: (child)=>child,
loaderTree: tree,
parentParams: {},
firstItem: true,
injectedCSS,
injectedJS,
injectedFontPreloadTags,
rootLayoutIncluded: false,
asNotFound: asNotFound,
metadataOutlet: /*#__PURE__*/ (0, _jsxruntime.jsx)(MetadataOutlet, {}),
missingSlots
});
// When the `vary` response header is present with `Next-URL`, that means there's a chance
// it could respond differently if there's an interception route. We provide this information
// to `AppRouter` so that it can properly seed the prefetch cache with a prefix, if needed.
const varyHeader = ctx.res.getHeader("vary");
const couldBeIntercepted = typeof varyHeader === "string" && varyHeader.includes(_approuterheaders.NEXT_URL);
return /*#__PURE__*/ (0, _jsxruntime.jsx)(AppRouter, {
buildId: ctx.renderOpts.buildId,
assetPrefix: ctx.assetPrefix,
urlParts: prepareInitialCanonicalUrl(urlPathname),
// This is the router state tree.
initialTree: initialTree,
// This is the tree of React nodes that are seeded into the cache
initialSeedData: seedData,
couldBeIntercepted: couldBeIntercepted,
initialHead: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
children: [
/*#__PURE__*/ (0, _jsxruntime.jsx)(NonIndex, {
ctx: ctx
}),
/*#__PURE__*/ (0, _jsxruntime.jsx)(MetadataTree, {}, ctx.requestId)
]
}),
globalErrorComponent: GlobalError,
// This is used to provide debug information (when in development mode)
// about which slots were not filled by page components while creating the component tree.
missingSlots: missingSlots
});
}
// This is the root component that runs in the RSC context
async function ReactServerError({ tree, ctx, errorType }) {
const { getDynamicParamFromSegment, query, appUsingSizeAdjustment, componentMod: { AppRouter, GlobalError, createDynamicallyTrackedSearchParams }, staticGenerationStore: { urlPathname }, requestId } = ctx;
const [MetadataTree] = (0, _metadata.createMetadataComponents)({
tree,
metadataContext: (0, _metadata.createMetadataContext)(urlPathname, ctx.renderOpts),
errorType,
query,
getDynamicParamFromSegment,
appUsingSizeAdjustment,
createDynamicallyTrackedSearchParams
});
const head = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
children: [
/*#__PURE__*/ (0, _jsxruntime.jsx)(MetadataTree, {}, requestId),
process.env.NODE_ENV === "development" && /*#__PURE__*/ (0, _jsxruntime.jsx)("meta", {
name: "next-error",
content: "not-found"
}),
/*#__PURE__*/ (0, _jsxruntime.jsx)(NonIndex, {
ctx: ctx
})
]
});
const initialTree = (0, _createflightrouterstatefromloadertree.createFlightRouterStateFromLoaderTree)(tree, getDynamicParamFromSegment, query);
// For metadata notFound error there's no global not found boundary on top
// so we create a not found page with AppRouter
const initialSeedData = [
initialTree[0],
{},
/*#__PURE__*/ (0, _jsxruntime.jsxs)("html", {
id: "__next_error__",
children: [
/*#__PURE__*/ (0, _jsxruntime.jsx)("head", {}),
/*#__PURE__*/ (0, _jsxruntime.jsx)("body", {})
]
}),
null
];
return /*#__PURE__*/ (0, _jsxruntime.jsx)(AppRouter, {
buildId: ctx.renderOpts.buildId,
assetPrefix: ctx.assetPrefix,
urlParts: prepareInitialCanonicalUrl(urlPathname),
initialTree: initialTree,
initialHead: head,
globalErrorComponent: GlobalError,
initialSeedData: initialSeedData,
missingSlots: new Set()
});
}
// This component must run in an SSR context. It will render the RSC root component
function ReactServerEntrypoint({ reactServerStream, preinitScripts, clientReferenceManifest, nonce }) {
preinitScripts();
const response = (0, _useflightresponse.useFlightStream)(reactServerStream, clientReferenceManifest, nonce);
return _react.default.use(response);
}
async function renderToHTMLOrFlightImpl(req, res, pagePath, query, renderOpts, baseCtx, requestEndedState) {
var _getTracer_getRootSpanAttributes, _staticGenerationStore_prerenderState;
const isNotFoundPath = pagePath === "/404";
// A unique request timestamp used by development to ensure that it's
// consistent and won't change during this request. This is important to
// avoid that resources can be deduped by React Float if the same resource is
// rendered or preloaded multiple times: `<link href="a.css?v={Date.now()}"/>`.
const requestTimestamp = Date.now();
const { buildManifest, subresourceIntegrityManifest, serverActionsManifest, ComponentMod, dev, nextFontManifest, supportsDynamicResponse, serverActions, appDirDevErrorLogger, assetPrefix = "", enableTainting } = renderOpts;
// We need to expose the bundled `require` API globally for
// react-server-dom-webpack. This is a hack until we find a better way.
if (ComponentMod.__next_app__) {
const instrumented = (0, _clientcomponentrendererlogger.wrapClientComponentLoader)(ComponentMod);
// @ts-ignore
globalThis.__next_require__ = instrumented.require;
// @ts-ignore
globalThis.__next_chunk_load__ = instrumented.loadChunk;
}
if (typeof req.on === "function") {
req.on("end", ()=>{
requestEndedState.ended = true;
if ("performance" in globalThis) {
const metrics = (0, _clientcomponentrendererlogger.getClientComponentLoaderMetrics)({
reset: true
});
if (metrics) {
(0, _tracer.getTracer)().startSpan(_constants.NextNodeServerSpan.clientComponentLoading, {
startTime: metrics.clientComponentLoadStart,
attributes: {
"next.clientComponentLoadCount": metrics.clientComponentLoadCount
}
}).end(metrics.clientComponentLoadStart + metrics.clientComponentLoadTimes);
}
}
});
}
const metadata = {};
const appUsingSizeAdjustment = !!(nextFontManifest == null ? void 0 : nextFontManifest.appUsingSizeAdjust);
// TODO: fix this typescript
const clientReferenceManifest = renderOpts.clientReferenceManifest;
const serverModuleMap = (0, _actionutils.createServerModuleMap)({
serverActionsManifest,
pageName: renderOpts.page
});
(0, _encryptionutils.setReferenceManifestsSingleton)({
clientReferenceManifest,
serverActionsManifest,
serverModuleMap
});
const digestErrorsMap = new Map();
const allCapturedErrors = [];
const isNextExport = !!renderOpts.nextExport;
const { staticGenerationStore, requestStore } = baseCtx;
const { isStaticGeneration } = staticGenerationStore;
// when static generation fails during PPR, we log the errors separately. We intentionally
// silence the error logger in this case to avoid double logging.
const silenceStaticGenerationErrors = renderOpts.experimental.ppr && isStaticGeneration;
const serverComponentsErrorHandler = (0, _createerrorhandler.createErrorHandler)({
source: _createerrorhandler.ErrorHandlerSource.serverComponents,
dev,
isNextExport,
errorLogger: appDirDevErrorLogger,
digestErrorsMap,
silenceLogger: silenceStaticGenerationErrors
});
const flightDataRendererErrorHandler = (0, _createerrorhandler.createErrorHandler)({
source: _createerrorhandler.ErrorHandlerSource.flightData,
dev,
isNextExport,
errorLogger: appDirDevErrorLogger,
digestErrorsMap,
silenceLogger: silenceStaticGenerationErrors
});
const htmlRendererErrorHandler = (0, _createerrorhandler.createErrorHandler)({
source: _createerrorhandler.ErrorHandlerSource.html,
dev,
isNextExport,
errorLogger: appDirDevErrorLogger,
digestErrorsMap,
allCapturedErrors,
silenceLogger: silenceStaticGenerationErrors
});
ComponentMod.patchFetch();
/**
* Rules of Static & Dynamic HTML:
*
* 1.) We must generate static HTML unless the caller explicitly opts
* in to dynamic HTML support.
*
* 2.) If dynamic HTML support is requested, we must honor that request
* or throw an error. It is the sole responsibility of the caller to
* ensure they aren't e.g. requesting dynamic HTML for an AMP page.
*
* These rules help ensure that other existing features like request caching,
* coalescing, and ISR continue working as intended.
*/ const generateStaticHTML = supportsDynamicResponse !== true;
// Pull out the hooks/references from the component.
const { tree: loaderTree, taintObjectReference } = ComponentMod;
if (enableTainting) {
taintObjectReference("Do not pass process.env to client components since it will leak sensitive data", process.env);
}
staticGenerationStore.fetchMetrics = [];
metadata.fetchMetrics = staticGenerationStore.fetchMetrics;
// don't modify original query object
query = {
...query
};
(0, _internalutils.stripInternalQueries)(query);
const isRSCRequest = req.headers[_approuterheaders.RSC_HEADER.toLowerCase()] !== undefined;
const isPrefetchRSCRequest = isRSCRequest && req.headers[_approuterheaders.NEXT_ROUTER_PREFETCH_HEADER.toLowerCase()] !== undefined;
/**
* Router state provided from the client-side router. Used to handle rendering
* from the common layout down. This value will be undefined if the request
* is not a client-side navigation request or if the request is a prefetch
* request (except when it's a prefetch request for an interception route
* which is always dynamic).
*/ const shouldProvideFlightRouterState = isRSCRequest && (!isPrefetchRSCRequest || !renderOpts.experimental.ppr || // Interception routes currently depend on the flight router state to
// extract dynamic params.
(0, _interceptionroutes.isInterceptionRouteAppPath)(pagePath));
const parsedFlightRouterState = (0, _parseandvalidateflightrouterstate.parseAndValidateFlightRouterState)(req.headers[_approuterheaders.NEXT_ROUTER_STATE_TREE.toLowerCase()]);
/**
* The metadata items array created in next-app-loader with all relevant information
* that we need to resolve the final metadata.
*/ let requestId;
if (process.env.NEXT_RUNTIME === "edge") {
requestId = crypto.randomUUID();
} else {
requestId = require("next/dist/compiled/nanoid").nanoid();
}
/**
* Dynamic parameters. E.g. when you visit `/dashboard/vercel` which is rendered by `/dashboard/[slug]` the value will be {"slug": "vercel"}.
*/ const params = renderOpts.params ?? {};
const getDynamicParamFromSegment = makeGetDynamicParamFromSegment(params, // `FlightRouterState` is unconditionally provided here because this method uses it
// to extract dynamic params as a fallback if they're not present in the path.
parsedFlightRouterState);
const ctx = {
...baseCtx,
getDynamicParamFromSegment,
query,
isPrefetch: isPrefetchRSCRequest,
requestTimestamp,
appUsingSizeAdjustment,
flightRouterState: shouldProvideFlightRouterState ? parsedFlightRouterState : undefined,
requestId,
defaultRevalidate: false,
pagePath,
clientReferenceManifest,
assetPrefix,
flightDataRendererErrorHandler,
serverComponentsErrorHandler,
isNotFoundPath,
res
};
if (isRSCRequest && !isStaticGeneration) {
return generateFlight(ctx);
}
// Create the resolver that can get the flight payload when it's ready or
// throw the error if it occurred. If we are not generating static HTML, we
// don't need to generate the flight payload because it's a dynamic request
// which means we're either getting the flight payload only or just the
// regular HTML.
const flightDataResolver = isStaticGeneration ? createFlightDataResolver(ctx) : null;
// Get the nonce from the incoming request if it has one.
const csp = req.headers["content-security-policy"] || req.headers["content-security-policy-report-only"];
let nonce;
if (csp && typeof csp === "string") {
nonce = (0, _getscriptnoncefromheader.getScriptNonceFromHeader)(csp);
}
const validateRootLayout = dev;
const { HeadManagerContext } = require("../../shared/lib/head-manager-context.shared-runtime");
// On each render, create a new `ServerInsertedHTML` context to capture
// injected nodes from user code (`useServerInsertedHTML`).
const { ServerInsertedHTMLProvider, renderServerInsertedHTML } = (0, _serverinsertedhtml.createServerInsertedHTML)();
(_getTracer_getRootSpanAttributes = (0, _tracer.getTracer)().getRootSpanAttributes()) == null ? void 0 : _getTracer_getRootSpanAttributes.set("next.route", pagePath);
const renderToStream = (0, _tracer.getTracer)().wrap(_constants.AppRenderSpan.getBodyResult, {
spanName: `render route (app) ${pagePath}`,
attributes: {
"next.route": pagePath
}
}, async ({ asNotFound, tree, formState })=>{
const polyfills = buildManifest.polyfillFiles.filter((polyfill)=>polyfill.endsWith(".js") && !polyfill.endsWith(".module.js")).map((polyfill)=>({
src: `${assetPrefix}/_next/${polyfill}${(0, _getassetquerystring.getAssetQueryString)(ctx, false)}`,
integrity: subresourceIntegrityManifest == null ? void 0 : subresourceIntegrityManifest[polyfill],
crossOrigin: renderOpts.crossOrigin,
noModule: true,
nonce
}));
const [preinitScripts, bootstrapScript] = (0, _requiredscripts.getRequiredScripts)(buildManifest, assetPrefix, renderOpts.crossOrigin, subresourceIntegrityManifest, (0, _getassetquerystring.getAssetQueryString)(ctx, true), nonce);
// We kick off the Flight Request (render) here. It is ok to initiate the render in an arbitrary
// place however it is critical that we only construct the Flight Response inside the SSR
// render so that directives like preloads are correctly piped through
const serverStream = ComponentMod.renderToReadableStream(/*#__PURE__*/ (0, _jsxruntime.jsx)(ReactServerApp, {
tree: tree,
ctx: ctx,
asNotFound: asNotFound
}), clientReferenceManifest.clientModules, {
onError: serverComponentsErrorHandler
});
// We are going to consume this render both for SSR and for inlining the flight data
let [renderStream, dataStream] = serverStream.tee();
const children = /*#__PURE__*/ (0, _jsxruntime.jsx)(HeadManagerContext.Provider, {
value: {
appDir: true,
nonce
},
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(ServerInsertedHTMLProvider, {
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(ReactServerEntrypoint, {
reactServerStream: renderStream,
preinitScripts: preinitScripts,
clientReferenceManifest: clientReferenceManifest,
nonce: nonce
})
})
});
const isResume = !!renderOpts.postponed;
const onHeaders = staticGenerationStore.prerenderState ? (headers)=>{
headers.forEach((value, key)=>{
metadata.headers ??= {};
metadata.headers[key] = value;
});
} : isStaticGeneration || isResume ? // ask React to emit headers. For Resume this is just not supported
// For static generation we know there will be an entire HTML document
// output and so moving from tag to header for preloading can only
// server to alter preloading priorities in unwanted ways
undefined : // early headers to the response
(headers)=>{
headers.forEach((value, key)=>{
res.appendHeader(key, value);
});
};
const getServerInsertedHTML = (0, _makegetserverinsertedhtml.makeGetServerInsertedHTML)({
polyfills,
renderServerInsertedHTML,
serverCapturedErrors: allCapturedErrors,
basePath: renderOpts.basePath
});
const renderer = (0, _staticrenderer.createStaticRenderer)({
ppr: renderOpts.experimental.ppr,
isStaticGeneration,
// If provided, the postpone state should be parsed as JSON so it can be
// provided to React.
postponed: typeof renderOpts.postponed === "string" ? JSON.parse(renderOpts.postponed) : null,
streamOptions: {
onError: htmlRendererErrorHandler,
onHeaders,
maxHeadersLength: 600,
nonce,
bootstrapScripts: [
bootstrapScript
],
formState
}
});
try {
let { stream, postponed, resumed } = await renderer.render(children);
const prerenderState = staticGenerationStore.prerenderState;
if (prerenderState) {
/**
* When prerendering there are three outcomes to consider
*
* Dynamic HTML: The prerender has dynamic holes (caused by using Next.js Dynamic Rendering APIs)
* We will need to resume this result when requests are handled and we don't include
* any server inserted HTML or inlined flight data in the static HTML
*
* Dynamic Data: The prerender has no dynamic holes but dynamic APIs were used. We will not
* resume this render when requests are handled but we will generate new inlined
* flight data since it is dynamic and differences may end up reconciling on the client
*
* Static: The prerender has no dynamic holes and no dynamic APIs were used. We statically encode
* all server inserted HTML and flight data
*/ // First we check if we have any dynamic holes in our HTML prerender
if ((0, _dynamicrendering.usedDynamicAPIs)(prerenderState)) {
if (postponed != null) {
// This is the Dynamic HTML case.
metadata.postponed = JSON.stringify((0, _staticrenderer.getDynamicHTMLPostponedState)(postponed));
} else {
// This is the Dynamic Data case
metadata.postponed = JSON.stringify((0, _staticrenderer.getDynamicDataPostponedState)());
}
// Regardless of whether this is the Dynamic HTML or Dynamic Data case we need to ensure we include
// server inserted html in the static response because the html that is part of the prerender may depend on it
// It is possible in the set of stream transforms for Dynamic HTML vs Dynamic Data may differ but currently both states
// require the same set so we unify the code path here
return {
stream: await (0, _nodewebstreamshelper.continueDynamicPrerender)(stream, {
getServerInsertedHTML
})
};
} else {
// We may still be rendering the RSC stream even though the HTML is finished.
// We wait for the RSC stream to complete and check again if dynamic was used
const [original, flightSpy] = dataStream.tee();
dataStream = original;
await (0, _useflightresponse.flightRenderComplete)(flightSpy);
if ((0, _dynamicrendering.usedDynamicAPIs)(prerenderState)) {
// This is the same logic above just repeated after ensuring the RSC stream itself has completed
if (postponed != null) {
// This is the Dynamic HTML case.
metadata.postponed = JSON.stringify((0, _staticrenderer.getDynamicHTMLPostponedState)(postponed));
} else {
// This is the Dynamic Data case
metadata.postponed = JSON.stringify((0, _staticrenderer.getDynamicDataPostponedState)());
}
// Regardless of whether this is the Dynamic HTML or Dynamic Data case we need to ensure we include
// server inserted html in the static response because the html that is part of the prerender may depend on it
// It is possible in the set of stream transforms for Dynamic HTML vs Dynamic Data may differ but currently both states
// require the same set so we unify the code path here
return {
stream: await (0, _nodewebstreamshelper.continueDynamicPrerender)(stream, {
getServerInsertedHTML
})
};
} else {
// This is the Static case
// We still have not used any dynamic APIs. At this point we can produce an entirely static prerender response
let renderedHTMLStream = stream;
if (staticGenerationStore.forceDynamic) {
throw new _staticgenerationbailout.StaticGenBailoutError('Invariant: a Page with `dynamic = "force-dynamic"` did not trigger the dynamic pathway. This is a bug in Next.js');
}
if (postponed != null) {
// We postponed but nothing dynamic was used. We resume the render now and immediately abort it
// so we can set all the postponed boundaries to client render mode before we store the HTML response
const resumeRenderer = (0, _staticrenderer.createStaticRenderer)({
ppr: true,
isStaticGeneration: false,
postponed: (0, _staticrenderer.getDynamicHTMLPostponedState)(postponed),
streamOptions: {
signal: (0, _dynamicrendering.createPostponedAbortSignal)("static prerender resume"),
onError: htmlRendererErrorHandler,
nonce
}
});
// We don't actually want to render anything so we just pass a stream
// that never resolves. The resume call is going to abort immediately anyway
const foreverStream = new ReadableStream();
const resumeChildren = /*#__PURE__*/ (0, _jsxruntime.jsx)(HeadManagerContext.Provider, {
value: {
appDir: true,
nonce
},
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(ServerInsertedHTMLProvider, {
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(ReactServerEntrypoint, {
reactServerStream: foreverStream,
preinitScripts: ()=>{},
clientReferenceManifest: clientReferenceManifest,
nonce: nonce
})
})
});
const { stream: resumeStream } = await resumeRenderer.render(resumeChildren);
// First we write everything from the prerender, then we write everything from the aborted resume render
renderedHTMLStream = (0, _nodewebstreamshelper.chainStreams)(stream, resumeStream);
}
return {
stream: await (0, _nodewebstreamshelper.continueStaticPrerender)(renderedHTMLStream, {
inlinedDataStream: (0, _useflightresponse.createInlinedDataReadableStream)(dataStream, nonce, formState),
getServerInsertedHTML
})
};
}
}
} else if (renderOpts.postponed) {
// This is a continuation of either an Incomplete or Dynamic Data Prerender.
const inlinedDataStream = (0, _useflightresponse.createInlinedDataReadableStream)(dataStream, nonce, formState);
if (resumed) {
// We have new HTML to stream and we also need to include server inserted HTML
return {
stream: await (0, _nodewebstreamshelper.continueDynamicHTMLResume)(stream, {
inlinedDataStream,
getServerInsertedHTML
})
};
} else {
// We are continuing a Dynamic Data Prerender and simply need to append new inlined flight data
return {
stream: await (0, _nodewebstreamshelper.continueDynamicDataResume)(stream, {
inlinedDataStream
})
};
}
} else {
// This may be a static render or a dynamic render
// @TODO factor this further to make the render types more clearly defined and remove
// the deluge of optional params that passed to configure the various behaviors
return {
stream: await (0, _nodewebstreamshelper.continueFizzStream)(stream, {
inlinedDataStream: (0, _useflightresponse.createInlinedDataReadableStream)(dataStream, nonce, formState),
isStaticGeneration: isStaticGeneration || generateStaticHTML,
getServerInsertedHTML,
serverInsertedHTMLToHead: true,
validateRootLayout
})
};
}
} catch (err) {
if ((0, _staticgenerationbailout.isStaticGenBailoutError)(err) || typeof err === "object" && err !== null && "message" in err && typeof err.message === "string" && err.message.includes("https://nextjs.org/docs/advanced-features/static-html-export")) {
// Ensure that "next dev" prints the red error overlay
throw err;
}
// If this is a static generation error, we need to throw it so that it
// can be handled by the caller if we're in static generation mode.
if (isStaticGeneration && (0, _hooksservercontext.isDynamicServerError)(err)) {
throw err;
}
// If a bailout made it to this point, it means it wasn't wrapped inside
// a suspense boundary.
const shouldBailoutToCSR = (0, _bailouttocsr.isBailoutToCSRError)(err);
if (shouldBailoutToCSR) {
const stack = (0, _formatservererror.getStackWithoutErrorMessage)(err);
if (renderOpts.experimental.missingSuspenseWithCSRBailout) {
(0, _log.error)(`${err.reason} should be wrapped in a suspense boundary at page "${pagePath}". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n${stack}`);
throw err;
}
(0, _log.warn)(`Entire page "${pagePath}" deopted into client-side rendering due to "${err.reason}". Read more: https://nextjs.org/docs/messages/deopted-into-client-rendering\n${stack}`);
}
if ((0, _notfound.isNotFoundError)(err)) {
res.statusCode = 404;
}
let hasRedirectError = false;
if ((0, _redirect.isRedirectError)(err)) {
hasRedirectError = true;
res.statusCode = (0, _redirect.getRedirectStatusCodeFromError)(err);
if (err.mutableCookies) {
const headers = new Headers();
// If there were mutable cookies set, we need to set them on the
// response.
if ((0, _requestcookies.appendMutableCookies)(headers, err.mutableCookies)) {
res.setHeader("set-cookie", Array.from(headers.values()));
}
}
const redirectUrl = (0, _addpathprefix.addPathPrefix)((0, _redirect.getURLFromRedirectError)(err), renderOpts.basePath);
res.setHeader("Location", redirectUrl);
}
const is404 = ctx.res.statusCode === 404;
if (!is404 && !hasRedirectError && !shouldBailoutToCSR) {
res.statusCode = 500;
}
const errorType = is404 ? "not-found" : hasRedirectError ? "redirect" : undefined;
const [errorPreinitScripts, errorBootstrapScript] = (0, _requiredscripts.getRequiredScripts)(buildManifest, assetPrefix, renderOpts.crossOrigin, subresourceIntegrityManifest, (0, _getassetquerystring.getAssetQueryString)(ctx, false), nonce);
const errorServerStream = ComponentMod.renderToReadableStream(/*#__PURE__*/ (0, _jsxruntime.jsx)(ReactServerError, {
tree: tree,
ctx: ctx,
errorType: errorType
}), clientReferenceManifest.clientModules, {
onError: serverComponentsErrorHandler
});
try {
const fizzStream = await (0, _nodewebstreamshelper.renderToInitialFizzStream)({
ReactDOMServer: require("react-dom/server.edge"),
element: /*#__PURE__*/ (0, _jsxruntime.jsx)(ReactServerEntrypoint, {
reactServerStream: errorServerStream,
preinitScripts: errorPreinitScripts,
clientReferenceManifest: clientReferenceManifest,
nonce: nonce
}),
streamOptions: {
nonce,
// Include hydration scripts in the HTML
bootstrapScripts: [
errorBootstrapScript
],
formState
}
});
return {
// Returning the error that was thrown so it can be used to handle
// the response in the caller.
err,
stream: await (0, _nodewebstreamshelper.continueFizzStream)(fizzStream, {
inlinedDataStream: (0, _useflightresponse.createInlinedDataReadableStream)(// This is intentionally using the readable datastream from the
// main render rather than the flight data from the error page
// render
dataStream, nonce, formState),
isStaticGeneration,
getServerInsertedHTML: (0, _makegetserverinsertedhtml.makeGetServerInsertedHTML)({
polyfills,
renderServerInsertedHTML,
serverCapturedErrors: [],
basePath: renderOpts.basePath
}),
serverInsertedHTMLToHead: true,
validateRootLayout
})
};
} catch (finalErr) {
if (process.env.NODE_ENV === "development" && (0, _notfound.isNotFoundError)(finalErr)) {
const bailOnNotFound = require("../../client/components/dev-root-not-found-boundary").bailOnNotFound;
bailOnNotFound();
}
throw finalErr;
}
}
});
// For action requests, we handle them differently with a special render result.
const actionRequestResult = await (0, _actionhandler.handleAction)({
req,
res,
ComponentMod,
serverModuleMap,
generateFlight,
staticGenerationStore,
requestStore,
serverActions,
ctx
});
let formState = null;
if (actionRequestResult) {
if (actionRequestResult.type === "not-found") {
const notFoundLoaderTree = createNotFoundLoaderTree(loaderTree);
const response = await renderToStream({
asNotFound: true,
tree: notFoundLoaderTree,
formState
});
return new _renderresult.default(response.stream, {
metadata
});
} else if (actionRequestResult.type === "done") {
if (actionRequestResult.result) {
actionRequestResult.result.assignMetadata(metadata);
return actionRequestResult.result;
} else if (actionRequestResult.formState) {
formState = actionRequestResult.formState;
}
}
}
const options = {
metadata
};
let response = await renderToStream({
asNotFound: isNotFoundPath,
tree: loaderTree,
formState
});
// If we have pending revalidates, wait until they are all resolved.
if (staticGenerationStore.pendingRevalidates) {
var _staticGenerationStore_incrementalCache;
options.waitUntil = Promise.all([
(_staticGenerationStore_incrementalCache = staticGenerationStore.incrementalCache) == null ? void 0 : _staticGenerationStore_incrementalCache.revalidateTag(staticGenerationStore.revalidatedTags || []),
...Object.values(staticGenerationStore.pendingRevalidates || {})
]);
}
(0, _patchfetch.addImplicitTags)(staticGenerationStore);
if (staticGenerationStore.tags) {
metadata.fetchTags = staticGenerationStore.tags.join(",");
}
// Create the new render result for the response.
const result = new _renderresult.default(response.stream, options);
// If we aren't performing static generation, we can return the result now.
if (!isStaticGeneration) {
return result;
}
// If this is static generation, we should read this in now rather than
// sending it back to be sent to the client.
response.stream = await result.toUnchunkedString(true);
const buildFailingError = digestErrorsMap.size > 0 ? digestErrorsMap.values().next().value : null;
// If we're debugging partial prerendering, print all the dynamic API accesses
// that occurred during the render.
if (staticGenerationStore.prerenderState && (0, _dynamicrendering.usedDynamicAPIs)(staticGenerationStore.prerenderState) && ((_staticGenerationStore_prerenderState = staticGenerationStore.prerenderState) == null ? void 0 : _staticGenerationStore_prerenderState.isDebugSkeleton)) {
(0, _log.warn)("The following dynamic usage was detected:");
for (const access of (0, _dynamicrendering.formatDynamicAPIAccesses)(staticGenerationStore.prerenderState)){
(0, _log.warn)(access);
}
}
if (!flightDataResolver) {
throw new Error("Invariant: Flight data resolver is missing when generating static HTML");
}
// If we encountered any unexpected errors during build we fail the
// prerendering phase and the build.
if (buildFailingError) {
throw buildFailingError;
}
// Wait for and collect the flight payload data if we don't have it
// already
const flightData = await flightDataResolver();
if (flightData) {
metadata.flightData = flightData;
}
// If force static is specifically set to false, we should not revalidate
// the page.
if (staticGenerationStore.forceStatic === false) {
staticGenerationStore.revalidate = 0;
}
// Copy the revalidation value onto the render result metadata.
metadata.revalidate = staticGenerationStore.revalidate ?? ctx.defaultRevalidate;
// provide bailout info for debugging
if (metadata.revalidate === 0) {
metadata.staticBailoutInfo = {
description: staticGenerationStore.dynamicUsageDescription,
stack: staticGenerationStore.dynamicUsageStack
};
}
return new _renderresult.default(response.stream, options);
}
const renderToHTMLOrFlight = (req, res, pagePath, query, renderOpts)=>{
// TODO: this includes query string, should it?
const pathname = (0, _validateurl.validateURL)(req.url);
return _requestasyncstoragewrapper.RequestAsyncStorageWrapper.wrap(renderOpts.ComponentMod.requestAsyncStorage, {
req,
res,
renderOpts
}, (requestStore)=>_staticgenerationasyncstoragewrapper.StaticGenerationAsyncStorageWrapper.wrap(renderOpts.ComponentMod.staticGenerationAsyncStorage, {
urlPathname: pathname,
renderOpts,
requestEndedState: {
ended: false
}
}, (staticGenerationStore)=>renderToHTMLOrFlightImpl(req, res, pagePath, query, renderOpts, {
requestStore,
staticGenerationStore,
componentMod: renderOpts.ComponentMod,
renderOpts
}, staticGenerationStore.requestEndedState || {})));
};
//# sourceMappingURL=app-render.js.map