UNPKG

next

Version:

The React Framework

233 lines (232 loc) • 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { exportAppPage: null, prospectiveRenderAppPage: null }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { exportAppPage: function() { return exportAppPage; }, prospectiveRenderAppPage: function() { return prospectiveRenderAppPage; } }); const _isdynamicusageerror = require("../helpers/is-dynamic-usage-error"); const _constants = require("../../lib/constants"); const _ciinfo = require("../../server/ci-info"); const _modulerender = require("../../server/route-modules/app-page/module.render"); const _bailouttocsr = require("../../shared/lib/lazy-dynamic/bailout-to-csr"); const _node = require("../../server/base-http/node"); const _approuterheaders = require("../../client/components/app-router-headers"); const _runwithafter = require("../../server/after/run-with-after"); async function prospectiveRenderAppPage(req, res, page, pathname, query, fallbackRouteParams, partialRenderOpts, sharedContext) { const afterRunner = new _runwithafter.AfterRunner(); // If the page is `/_not-found`, then we should update the page to be `/404`. // UNDERSCORE_NOT_FOUND_ROUTE value used here, however we don't want to import it here as it causes constants to be inlined which we don't want here. if (page === '/_not-found/page') { pathname = '/404'; } try { await (0, _modulerender.lazyRenderAppPage)(new _node.NodeNextRequest(req), new _node.NodeNextResponse(res), pathname, query, fallbackRouteParams, { ...partialRenderOpts, waitUntil: afterRunner.context.waitUntil, onClose: afterRunner.context.onClose, onAfterTaskError: afterRunner.context.onTaskError }, undefined, false, sharedContext); // TODO(after): if we abort a prerender because of an error in an after-callback // we should probably communicate that better (and not log the error twice) await afterRunner.executeAfter(); } catch (err) { if (!(0, _isdynamicusageerror.isDynamicUsageError)(err)) { throw err; } // We should fail rendering if a client side rendering bailout // occurred at the page level. if ((0, _bailouttocsr.isBailoutToCSRError)(err)) { throw err; } } } async function exportAppPage(req, res, page, path, pathname, query, fallbackRouteParams, partialRenderOpts, htmlFilepath, debugOutput, isDynamicError, fileWriter, sharedContext) { const afterRunner = new _runwithafter.AfterRunner(); const renderOpts = { ...partialRenderOpts, waitUntil: afterRunner.context.waitUntil, onClose: afterRunner.context.onClose, onAfterTaskError: afterRunner.context.onTaskError }; let isDefaultNotFound = false; // If the page is `/_not-found`, then we should update the page to be `/404`. // UNDERSCORE_NOT_FOUND_ROUTE value used here, however we don't want to import it here as it causes constants to be inlined which we don't want here. if (page === '/_not-found/page') { isDefaultNotFound = true; pathname = '/404'; } try { const result = await (0, _modulerender.lazyRenderAppPage)(new _node.NodeNextRequest(req), new _node.NodeNextResponse(res), pathname, query, fallbackRouteParams, renderOpts, undefined, false, sharedContext); const html = result.toUnchunkedString(); // TODO(after): if we abort a prerender because of an error in an after-callback // we should probably communicate that better (and not log the error twice) await afterRunner.executeAfter(); const { metadata } = result; const { flightData, cacheControl = { revalidate: false, expire: undefined }, postponed, fetchTags, fetchMetrics, segmentData } = metadata; // Ensure we don't postpone without having PPR enabled. if (postponed && !renderOpts.experimental.isRoutePPREnabled) { throw Object.defineProperty(new Error('Invariant: page postponed without PPR being enabled'), "__NEXT_ERROR_CODE", { value: "E156", enumerable: false, configurable: true }); } if (cacheControl.revalidate === 0) { if (isDynamicError) { throw Object.defineProperty(new Error(`Page with dynamic = "error" encountered dynamic data method on ${path}.`), "__NEXT_ERROR_CODE", { value: "E388", enumerable: false, configurable: true }); } const { staticBailoutInfo = {} } = metadata; if (debugOutput && (staticBailoutInfo == null ? void 0 : staticBailoutInfo.description)) { logDynamicUsageWarning({ path, description: staticBailoutInfo.description, stack: staticBailoutInfo.stack }); } return { cacheControl, fetchMetrics }; } // If page data isn't available, it means that the page couldn't be rendered // properly so long as we don't have unknown route params. When a route doesn't // have unknown route params, there will not be any flight data. if (!flightData && (!fallbackRouteParams || fallbackRouteParams.size === 0)) { throw Object.defineProperty(new Error(`Invariant: failed to get page data for ${path}`), "__NEXT_ERROR_CODE", { value: "E194", enumerable: false, configurable: true }); } if (flightData) { // If PPR is enabled, we want to emit a prefetch rsc file for the page // instead of the standard rsc. This is because the standard rsc will // contain the dynamic data. We do this if any routes have PPR enabled so // that the cache read/write is the same. if (renderOpts.experimental.isRoutePPREnabled) { // If PPR is enabled, we should emit the flight data as the prefetch // payload. // TODO: This will eventually be replaced by the per-segment prefetch // output below. fileWriter.append(htmlFilepath.replace(/\.html$/, _constants.RSC_PREFETCH_SUFFIX), flightData); } else { // Writing the RSC payload to a file if we don't have PPR enabled. fileWriter.append(htmlFilepath.replace(/\.html$/, _constants.RSC_SUFFIX), flightData); } } let segmentPaths; if (segmentData) { // Emit the per-segment prefetch data. We emit them as separate files // so that the cache handler has the option to treat each as a // separate entry. segmentPaths = []; const segmentsDir = htmlFilepath.replace(/\.html$/, _constants.RSC_SEGMENTS_DIR_SUFFIX); for (const [segmentPath, buffer] of segmentData){ segmentPaths.push(segmentPath); const segmentDataFilePath = segmentsDir + segmentPath + _constants.RSC_SEGMENT_SUFFIX; fileWriter.append(segmentDataFilePath, buffer); } } const headers = { ...metadata.headers }; // If we're writing the file to disk, we know it's a prerender. headers[_approuterheaders.NEXT_IS_PRERENDER_HEADER] = '1'; if (fetchTags) { headers[_constants.NEXT_CACHE_TAGS_HEADER] = fetchTags; } // Writing static HTML to a file. fileWriter.append(htmlFilepath, html ?? ''); const isParallelRoute = /\/@\w+/.test(page); const isNonSuccessfulStatusCode = res.statusCode > 300; // When PPR is enabled, we don't always send 200 for routes that have been // pregenerated, so we should grab the status code from the mocked // response. let status = renderOpts.experimental.isRoutePPREnabled ? res.statusCode : undefined; if (isDefaultNotFound) { // Override the default /_not-found page status code to 404 status = 404; } else if (isNonSuccessfulStatusCode && !isParallelRoute) { // If it's parallel route the status from mock response is 404 status = res.statusCode; } // Writing the request metadata to a file. const meta = { status, headers, postponed, segmentPaths }; fileWriter.append(htmlFilepath.replace(/\.html$/, _constants.NEXT_META_SUFFIX), JSON.stringify(meta, null, 2)); return { // Only include the metadata if the environment has next support. metadata: _ciinfo.hasNextSupport ? meta : undefined, hasEmptyPrelude: Boolean(postponed) && html === '', hasPostponed: Boolean(postponed), cacheControl, fetchMetrics }; } catch (err) { if (!(0, _isdynamicusageerror.isDynamicUsageError)(err)) { throw err; } // We should fail rendering if a client side rendering bailout // occurred at the page level. if ((0, _bailouttocsr.isBailoutToCSRError)(err)) { throw err; } let fetchMetrics; if (debugOutput) { const store = renderOpts.store; const { dynamicUsageDescription, dynamicUsageStack } = store; fetchMetrics = store.fetchMetrics; logDynamicUsageWarning({ path, description: dynamicUsageDescription ?? '', stack: dynamicUsageStack }); } return { cacheControl: { revalidate: 0, expire: undefined }, fetchMetrics }; } } function logDynamicUsageWarning({ path, description, stack }) { const errMessage = Object.defineProperty(new Error(`Static generation failed due to dynamic usage on ${path}, reason: ${description}`), "__NEXT_ERROR_CODE", { value: "E381", enumerable: false, configurable: true }); if (stack) { errMessage.stack = errMessage.message + stack.substring(stack.indexOf('\n')); } console.warn(errMessage); } //# sourceMappingURL=app-page.js.map