UNPKG

next

Version:

The React Framework

997 lines • 55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderToHTML = renderToHTML; var _react = _interopRequireDefault(require("react")); var _querystring = require("querystring"); var _reactServerDomWebpack = require("next/dist/compiled/react-server-dom-webpack"); var _writerBrowserServer = require("next/dist/compiled/react-server-dom-webpack/writer.browser.server"); var _styledJsx = require("styled-jsx"); var _constants = require("../lib/constants"); var _constants1 = require("../shared/lib/constants"); var _isSerializableProps = require("../lib/is-serializable-props"); var _amp = require("../shared/lib/amp"); var _ampContext = require("../shared/lib/amp-context"); var _head = require("../shared/lib/head"); var _headManagerContext = require("../shared/lib/head-manager-context"); var _loadable = _interopRequireDefault(require("../shared/lib/loadable")); var _loadableContext = require("../shared/lib/loadable-context"); var _routerContext = require("../shared/lib/router-context"); var _isDynamic = require("../shared/lib/router/utils/is-dynamic"); var _utils = require("../shared/lib/utils"); var _htmlContext = require("../shared/lib/html-context"); var _denormalizePagePath = require("./denormalize-page-path"); var _normalizePagePath = require("./normalize-page-path"); var _requestMeta = require("./request-meta"); var _loadCustomRoutes = require("../lib/load-custom-routes"); var _renderResult = _interopRequireDefault(require("./render-result")); var _isError = _interopRequireDefault(require("../lib/is-error")); var _nodeWebStreamsHelper = require("./node-web-streams-helper"); var _imageConfigContext = require("../shared/lib/image-config-context"); var _flushEffects = require("../shared/lib/flush-effects"); var _interopDefault = require("../lib/interop-default"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } let optimizeAmp; let getFontDefinitionFromManifest; let tryGetPreviewData; let warn; let postProcess; const DOCTYPE = '<!DOCTYPE html>'; if (!process.browser) { require('./node-polyfill-web-streams'); optimizeAmp = require('./optimize-amp').default; getFontDefinitionFromManifest = require('./font-utils').getFontDefinitionFromManifest; tryGetPreviewData = require('./api-utils/node').tryGetPreviewData; warn = require('../build/output/log').warn; postProcess = require('../shared/lib/post-process').default; } else { warn = console.warn.bind(console); } function noRouter() { const message = 'No router instance found. you should only use "next/router" inside the client side of your app. https://nextjs.org/docs/messages/no-router-instance'; throw new Error(message); } class ServerRouter { constructor(pathname, query, as, { isFallback }, isReady, basePath, locale, locales, defaultLocale, domainLocales, isPreview, isLocaleDomain){ this.route = pathname.replace(/\/$/, '') || '/'; this.pathname = pathname; this.query = query; this.asPath = as; this.isFallback = isFallback; this.basePath = basePath; this.locale = locale; this.locales = locales; this.defaultLocale = defaultLocale; this.isReady = isReady; this.domainLocales = domainLocales; this.isPreview = !!isPreview; this.isLocaleDomain = !!isLocaleDomain; } push() { noRouter(); } replace() { noRouter(); } reload() { noRouter(); } back() { noRouter(); } prefetch() { noRouter(); } beforePopState() { noRouter(); } } function enhanceComponents(options, App, Component) { // For backwards compatibility if (typeof options === 'function') { return { App, Component: options(Component) }; } return { App: options.enhanceApp ? options.enhanceApp(App) : App, Component: options.enhanceComponent ? options.enhanceComponent(Component) : Component }; } function renderFlight(AppMod, ComponentMod, props) { const isServerComponent = !!ComponentMod.__next_rsc__; const App = (0, _interopDefault).interopDefault(AppMod); const Component = (0, _interopDefault).interopDefault(ComponentMod); const AppServer = isServerComponent ? App : _react.default.Fragment; return(/*#__PURE__*/ _react.default.createElement(AppServer, null, /*#__PURE__*/ _react.default.createElement(Component, Object.assign({}, props)))); } const invalidKeysMsg = (methodName, invalidKeys)=>{ const docsPathname = `invalid-${methodName.toLocaleLowerCase()}-value`; return `Additional keys were returned from \`${methodName}\`. Properties intended for your component must be nested under the \`props\` key, e.g.:` + `\n\n\treturn { props: { title: 'My Title', content: '...' } }` + `\n\nKeys that need to be moved: ${invalidKeys.join(', ')}.` + `\nRead more: https://nextjs.org/docs/messages/${docsPathname}`; }; function checkRedirectValues(redirect, req, method) { const { destination , permanent , statusCode , basePath } = redirect; let errors = []; const hasStatusCode = typeof statusCode !== 'undefined'; const hasPermanent = typeof permanent !== 'undefined'; if (hasPermanent && hasStatusCode) { errors.push(`\`permanent\` and \`statusCode\` can not both be provided`); } else if (hasPermanent && typeof permanent !== 'boolean') { errors.push(`\`permanent\` must be \`true\` or \`false\``); } else if (hasStatusCode && !_loadCustomRoutes.allowedStatusCodes.has(statusCode)) { errors.push(`\`statusCode\` must undefined or one of ${[ ..._loadCustomRoutes.allowedStatusCodes ].join(', ')}`); } const destinationType = typeof destination; if (destinationType !== 'string') { errors.push(`\`destination\` should be string but received ${destinationType}`); } const basePathType = typeof basePath; if (basePathType !== 'undefined' && basePathType !== 'boolean') { errors.push(`\`basePath\` should be undefined or a false, received ${basePathType}`); } if (errors.length > 0) { throw new Error(`Invalid redirect object returned from ${method} for ${req.url}\n` + errors.join(' and ') + '\n' + `See more info here: https://nextjs.org/docs/messages/invalid-redirect-gssp`); } } const rscCache = new Map(); function createFlightHook() { return ({ id , req , inlinedDataWritable , staticDataWritable , bootstrap })=>{ let entry = rscCache.get(id); if (!entry) { const [renderStream, forwardStream] = (0, _nodeWebStreamsHelper).readableStreamTee(req); entry = (0, _reactServerDomWebpack).createFromReadableStream(renderStream); rscCache.set(id, entry); let bootstrapped = false; const forwardReader = forwardStream.getReader(); const inlinedDataWriter = inlinedDataWritable.getWriter(); const staticDataWriter = staticDataWritable ? staticDataWritable.getWriter() : null; function process() { forwardReader.read().then(({ done , value })=>{ if (bootstrap && !bootstrapped) { bootstrapped = true; inlinedDataWriter.write((0, _nodeWebStreamsHelper).encodeText(`<script>(self.__next_s=self.__next_s||[]).push(${JSON.stringify([ 0, id ])})</script>`)); } if (done) { rscCache.delete(id); inlinedDataWriter.close(); if (staticDataWriter) { staticDataWriter.close(); } } else { inlinedDataWriter.write((0, _nodeWebStreamsHelper).encodeText(`<script>(self.__next_s=self.__next_s||[]).push(${JSON.stringify([ 1, id, (0, _nodeWebStreamsHelper).decodeText(value) ])})</script>`)); if (staticDataWriter) { staticDataWriter.write(value); } process(); } }); } process(); } return entry; }; } const useFlightResponse = createFlightHook(); // Create the wrapper component for a Flight stream. function createServerComponentRenderer(AppMod, ComponentMod, { cachePrefix , inlinedTransformStream , staticTransformStream , serverComponentManifest }) { // We need to expose the `__webpack_require__` API globally for // react-server-dom-webpack. This is a hack until we find a better way. // @ts-ignore globalThis.__webpack_require__ = ComponentMod.__next_rsc__.__webpack_require__; const Component = (0, _interopDefault).interopDefault(ComponentMod); function ServerComponentWrapper(props) { const id = _react.default.useId(); const reqStream = (0, _writerBrowserServer).renderToReadableStream(renderFlight(AppMod, ComponentMod, props), serverComponentManifest); const response = useFlightResponse({ id: cachePrefix + ',' + id, req: reqStream, inlinedDataWritable: inlinedTransformStream.writable, staticDataWritable: staticTransformStream ? staticTransformStream.writable : null, bootstrap: true }); const root = response.readRoot(); rscCache.delete(id); return root; } for (const methodName of Object.keys(Component)){ const method = Component[methodName]; if (method) { ServerComponentWrapper[methodName] = method; } } return ServerComponentWrapper; } async function renderToHTML(req, res, pathname, query, renderOpts) { var ref, ref1; // In dev we invalidate the cache by appending a timestamp to the resource URL. // This is a workaround to fix https://github.com/vercel/next.js/issues/5860 // TODO: remove this workaround when https://bugs.webkit.org/show_bug.cgi?id=187726 is fixed. renderOpts.devOnlyCacheBusterQueryString = renderOpts.dev ? renderOpts.devOnlyCacheBusterQueryString || `?ts=${Date.now()}` : ''; // don't modify original query object query = Object.assign({}, query); const { err , dev =false , ampPath ='' , pageConfig ={} , buildManifest , fontManifest , reactLoadableManifest , ErrorDebug , getStaticProps , getStaticPaths , getServerSideProps , serverComponentManifest , isDataReq , params , previewProps , basePath , devOnlyCacheBusterQueryString , supportsDynamicHTML , images , reactRoot , runtime: globalRuntime , ComponentMod , AppMod: AppClientMod , AppServerMod , } = renderOpts; const hasConcurrentFeatures = reactRoot; let Document = renderOpts.Document; // We don't need to opt-into the flight inlining logic if the page isn't a RSC. const isServerComponent = hasConcurrentFeatures && !!serverComponentManifest && !!((ref = ComponentMod.__next_rsc__) === null || ref === void 0 ? void 0 : ref.server); let Component = renderOpts.Component; const AppMod = isServerComponent ? AppServerMod : AppClientMod; const App = (0, _interopDefault).interopDefault(AppMod); let serverComponentsInlinedTransformStream = null; let serverComponentsPageDataTransformStream = isServerComponent && !process.browser ? new TransformStream() : null; if (isServerComponent) { serverComponentsInlinedTransformStream = new TransformStream(); const search = (0, _querystring).stringify(query); Component = createServerComponentRenderer(AppMod, ComponentMod, { cachePrefix: pathname + (search ? `?${search}` : ''), inlinedTransformStream: serverComponentsInlinedTransformStream, staticTransformStream: serverComponentsPageDataTransformStream, serverComponentManifest }); } const getFontDefinition = (url)=>{ if (fontManifest) { return getFontDefinitionFromManifest(url, fontManifest); } return ''; }; let renderServerComponentData = isServerComponent ? query.__flight__ !== undefined : false; const serverComponentProps = isServerComponent && query.__props__ ? JSON.parse(query.__props__) : undefined; delete query.__flight__; delete query.__props__; const callMiddleware = async (method, args, props = false)=>{ let results = props ? {} : []; if (Document[`${method}Middleware`]) { let middlewareFunc = await Document[`${method}Middleware`]; middlewareFunc = middlewareFunc.default || middlewareFunc; const curResults = await middlewareFunc(...args); if (props) { for (const result of curResults){ results = { ...results, ...result }; } } else { results = curResults; } } return results; }; const headTags = (...args)=>callMiddleware('headTags', args) ; const isFallback = !!query.__nextFallback; const notFoundSrcPage = query.__nextNotFoundSrcPage; delete query.__nextFallback; delete query.__nextLocale; delete query.__nextDefaultLocale; delete query.__nextIsNotFound; const isSSG = !!getStaticProps; const isBuildTimeSSG = isSSG && renderOpts.nextExport; const defaultAppGetInitialProps = App.getInitialProps === App.origGetInitialProps; const hasPageGetInitialProps = !!((ref1 = Component) === null || ref1 === void 0 ? void 0 : ref1.getInitialProps); const pageIsDynamic = (0, _isDynamic).isDynamicRoute(pathname); const isAutoExport = !hasPageGetInitialProps && defaultAppGetInitialProps && !isSSG && !getServerSideProps && !isServerComponent; for (const methodName of [ 'getStaticProps', 'getServerSideProps', 'getStaticPaths', ]){ var ref2; if ((ref2 = Component) === null || ref2 === void 0 ? void 0 : ref2[methodName]) { throw new Error(`page ${pathname} ${methodName} ${_constants.GSSP_COMPONENT_MEMBER_ERROR}`); } } if (hasPageGetInitialProps && isSSG) { throw new Error(_constants.SSG_GET_INITIAL_PROPS_CONFLICT + ` ${pathname}`); } if (hasPageGetInitialProps && getServerSideProps) { throw new Error(_constants.SERVER_PROPS_GET_INIT_PROPS_CONFLICT + ` ${pathname}`); } if (getServerSideProps && isSSG) { throw new Error(_constants.SERVER_PROPS_SSG_CONFLICT + ` ${pathname}`); } if (getStaticPaths && !pageIsDynamic) { throw new Error(`getStaticPaths is only allowed for dynamic SSG pages and was found on '${pathname}'.` + `\nRead more: https://nextjs.org/docs/messages/non-dynamic-getstaticpaths-usage`); } if (!!getStaticPaths && !isSSG) { throw new Error(`getStaticPaths was added without a getStaticProps in ${pathname}. Without getStaticProps, getStaticPaths does nothing`); } if (isSSG && pageIsDynamic && !getStaticPaths) { throw new Error(`getStaticPaths is required for dynamic SSG pages and is missing for '${pathname}'.` + `\nRead more: https://nextjs.org/docs/messages/invalid-getstaticpaths-value`); } let asPath = renderOpts.resolvedAsPath || req.url; if (dev) { const { isValidElementType } = require('next/dist/compiled/react-is'); if (!isValidElementType(Component)) { throw new Error(`The default export is not a React Component in page: "${pathname}"`); } if (!isValidElementType(App)) { throw new Error(`The default export is not a React Component in page: "/_app"`); } if (!isValidElementType(Document)) { throw new Error(`The default export is not a React Component in page: "/_document"`); } if (isAutoExport || isFallback) { // remove query values except ones that will be set during export query = { ...query.amp ? { amp: query.amp } : {} }; asPath = `${pathname}${// ensure trailing slash is present for non-dynamic auto-export pages req.url.endsWith('/') && pathname !== '/' && !pageIsDynamic ? '/' : ''}`; req.url = pathname; } if (pathname === '/404' && (hasPageGetInitialProps || getServerSideProps)) { throw new Error(`\`pages/404\` ${_constants.STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR}`); } if (_constants1.STATIC_STATUS_PAGES.includes(pathname) && (hasPageGetInitialProps || getServerSideProps)) { throw new Error(`\`pages${pathname}\` ${_constants.STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR}`); } } await _loadable.default.preloadAll() // Make sure all dynamic imports are loaded ; let isPreview; let previewData; if ((isSSG || getServerSideProps) && !isFallback && !process.browser) { // Reads of this are cached on the `req` object, so this should resolve // instantly. There's no need to pass this data down from a previous // invoke, where we'd have to consider server & serverless. previewData = tryGetPreviewData(req, res, previewProps); isPreview = previewData !== false; } // url will always be set const routerIsReady = !!(getServerSideProps || hasPageGetInitialProps || !defaultAppGetInitialProps && !isSSG); const router = new ServerRouter(pathname, query, asPath, { isFallback: isFallback }, routerIsReady, basePath, renderOpts.locale, renderOpts.locales, renderOpts.defaultLocale, renderOpts.domainLocales, isPreview, (0, _requestMeta).getRequestMeta(req, '__nextIsLocaleDomain')); const jsxStyleRegistry = (0, _styledJsx).createStyleRegistry(); const ctx = { err, req: isAutoExport ? undefined : req, res: isAutoExport ? undefined : res, pathname, query, asPath, locale: renderOpts.locale, locales: renderOpts.locales, defaultLocale: renderOpts.defaultLocale, AppTree: (props)=>{ return(/*#__PURE__*/ _react.default.createElement(AppContainerWithIsomorphicFiberStructure, null, renderFlight(AppMod, ComponentMod, props))); }, defaultGetInitialProps: async (docCtx, options = {})=>{ const enhanceApp = (AppComp)=>{ return (props)=>/*#__PURE__*/ _react.default.createElement(AppComp, Object.assign({}, props)) ; }; const { html , head } = await docCtx.renderPage({ enhanceApp }); const styles = jsxStyleRegistry.styles({ nonce: options.nonce }); return { html, head, styles }; } }; let props1; const ampState = { ampFirst: pageConfig.amp === true, hasQuery: Boolean(query.amp), hybrid: pageConfig.amp === 'hybrid' }; // Disable AMP under the web environment const inAmpMode = !process.browser && (0, _amp).isInAmpMode(ampState); const reactLoadableModules = []; let head1 = (0, _head).defaultHead(inAmpMode); let scriptLoader = {}; const nextExport = !isSSG && (renderOpts.nextExport || dev && (isAutoExport || isFallback)); const styledJsxFlushEffect = ()=>{ const styles = jsxStyleRegistry.styles(); jsxStyleRegistry.flush(); return(/*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, styles)); }; let flushEffects = null; function FlushEffectContainer({ children }) { // If the client tree suspends, this component will be rendered multiple // times before we flush. To ensure we don't call old callbacks corresponding // to a previous render, we clear any registered callbacks whenever we render. flushEffects = null; const flushEffectsImpl = _react.default.useCallback((callbacks)=>{ if (flushEffects) { throw new Error('The `useFlushEffects` hook cannot be used more than once.' + '\nRead more: https://nextjs.org/docs/messages/multiple-flush-effects'); } flushEffects = callbacks; }, []); return(/*#__PURE__*/ _react.default.createElement(_flushEffects.FlushEffectsContext.Provider, { value: flushEffectsImpl }, children)); } const AppContainer = ({ children })=>/*#__PURE__*/ _react.default.createElement(FlushEffectContainer, null, /*#__PURE__*/ _react.default.createElement(_routerContext.RouterContext.Provider, { value: router }, /*#__PURE__*/ _react.default.createElement(_ampContext.AmpStateContext.Provider, { value: ampState }, /*#__PURE__*/ _react.default.createElement(_headManagerContext.HeadManagerContext.Provider, { value: { updateHead: (state)=>{ head1 = state; }, updateScripts: (scripts)=>{ scriptLoader = scripts; }, scripts: {}, mountedInstances: new Set() } }, /*#__PURE__*/ _react.default.createElement(_loadableContext.LoadableContext.Provider, { value: (moduleName)=>reactLoadableModules.push(moduleName) }, /*#__PURE__*/ _react.default.createElement(_styledJsx.StyleRegistry, { registry: jsxStyleRegistry }, /*#__PURE__*/ _react.default.createElement(_imageConfigContext.ImageConfigContext.Provider, { value: images }, children))))))) ; // The `useId` API uses the path indexes to generate an ID for each node. // To guarantee the match of hydration, we need to ensure that the structure // of wrapper nodes is isomorphic in server and client. // TODO: With `enhanceApp` and `enhanceComponents` options, this approach may // not be useful. // https://github.com/facebook/react/pull/22644 const Noop = ()=>null ; const AppContainerWithIsomorphicFiberStructure = ({ children })=>{ return(/*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/ _react.default.createElement(Noop, null), /*#__PURE__*/ _react.default.createElement(AppContainer, null, /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, dev ? /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, children, /*#__PURE__*/ _react.default.createElement(Noop, null)) : children, /*#__PURE__*/ _react.default.createElement(Noop, null))))); }; props1 = await (0, _utils).loadGetInitialProps(App, { AppTree: ctx.AppTree, Component, router, ctx }); if ((isSSG || getServerSideProps) && isPreview) { props1.__N_PREVIEW = true; } if (isSSG) { props1[_constants1.STATIC_PROPS_ID] = true; } if (isSSG && !isFallback) { let data; try { data = await getStaticProps({ ...pageIsDynamic ? { params: query } : undefined, ...isPreview ? { preview: true, previewData: previewData } : undefined, locales: renderOpts.locales, locale: renderOpts.locale, defaultLocale: renderOpts.defaultLocale }); } catch (staticPropsError) { // remove not found error code to prevent triggering legacy // 404 rendering if (staticPropsError && staticPropsError.code === 'ENOENT') { delete staticPropsError.code; } throw staticPropsError; } if (data == null) { throw new Error(_constants.GSP_NO_RETURNED_VALUE); } const invalidKeys = Object.keys(data).filter((key)=>key !== 'revalidate' && key !== 'props' && key !== 'redirect' && key !== 'notFound' ); if (invalidKeys.includes('unstable_revalidate')) { throw new Error(_constants.UNSTABLE_REVALIDATE_RENAME_ERROR); } if (invalidKeys.length) { throw new Error(invalidKeysMsg('getStaticProps', invalidKeys)); } if (process.env.NODE_ENV !== 'production') { if (typeof data.notFound !== 'undefined' && typeof data.redirect !== 'undefined') { throw new Error(`\`redirect\` and \`notFound\` can not both be returned from ${isSSG ? 'getStaticProps' : 'getServerSideProps'} at the same time. Page: ${pathname}\nSee more info here: https://nextjs.org/docs/messages/gssp-mixed-not-found-redirect`); } } if ('notFound' in data && data.notFound) { if (pathname === '/404') { throw new Error(`The /404 page can not return notFound in "getStaticProps", please remove it to continue!`); } renderOpts.isNotFound = true; } if ('redirect' in data && data.redirect && typeof data.redirect === 'object') { checkRedirectValues(data.redirect, req, 'getStaticProps'); if (isBuildTimeSSG) { throw new Error(`\`redirect\` can not be returned from getStaticProps during prerendering (${req.url})\n` + `See more info here: https://nextjs.org/docs/messages/gsp-redirect-during-prerender`); } data.props = { __N_REDIRECT: data.redirect.destination, __N_REDIRECT_STATUS: (0, _loadCustomRoutes).getRedirectStatus(data.redirect) }; if (typeof data.redirect.basePath !== 'undefined') { data.props.__N_REDIRECT_BASE_PATH = data.redirect.basePath; } renderOpts.isRedirect = true; } if ((dev || isBuildTimeSSG) && !renderOpts.isNotFound && !(0, _isSerializableProps).isSerializableProps(pathname, 'getStaticProps', data.props)) { // this fn should throw an error instead of ever returning `false` throw new Error('invariant: getStaticProps did not return valid props. Please report this.'); } if ('revalidate' in data) { if (typeof data.revalidate === 'number') { if (!Number.isInteger(data.revalidate)) { throw new Error(`A page's revalidate option must be seconds expressed as a natural number for ${req.url}. Mixed numbers, such as '${data.revalidate}', cannot be used.` + `\nTry changing the value to '${Math.ceil(data.revalidate)}' or using \`Math.ceil()\` if you're computing the value.`); } else if (data.revalidate <= 0) { throw new Error(`A page's revalidate option can not be less than or equal to zero for ${req.url}. A revalidate option of zero means to revalidate after _every_ request, and implies stale data cannot be tolerated.` + `\n\nTo never revalidate, you can set revalidate to \`false\` (only ran once at build-time).` + `\nTo revalidate as soon as possible, you can set the value to \`1\`.`); } else if (data.revalidate > 31536000) { // if it's greater than a year for some reason error console.warn(`Warning: A page's revalidate option was set to more than a year for ${req.url}. This may have been done in error.` + `\nTo only run getStaticProps at build-time and not revalidate at runtime, you can set \`revalidate\` to \`false\`!`); } } else if (data.revalidate === true) { // When enabled, revalidate after 1 second. This value is optimal for // the most up-to-date page possible, but without a 1-to-1 // request-refresh ratio. data.revalidate = 1; } else if (data.revalidate === false || typeof data.revalidate === 'undefined') { // By default, we never revalidate. data.revalidate = false; } else { throw new Error(`A page's revalidate option must be seconds expressed as a natural number. Mixed numbers and strings cannot be used. Received '${JSON.stringify(data.revalidate)}' for ${req.url}`); } } else { data.revalidate = false; } props1.pageProps = Object.assign({}, props1.pageProps, 'props' in data ? data.props : undefined); renderOpts.revalidate = 'revalidate' in data ? data.revalidate : undefined; renderOpts.pageData = props1; // this must come after revalidate is added to renderOpts if (renderOpts.isNotFound) { return null; } } if (getServerSideProps) { props1[_constants1.SERVER_PROPS_ID] = true; } if (getServerSideProps && !isFallback) { let data; let canAccessRes = true; let resOrProxy = res; let deferredContent = false; if (process.env.NODE_ENV !== 'production') { resOrProxy = new Proxy(res, { get: function(obj, prop, receiver) { if (!canAccessRes) { const message = `You should not access 'res' after getServerSideProps resolves.` + `\nRead more: https://nextjs.org/docs/messages/gssp-no-mutating-res`; if (deferredContent) { throw new Error(message); } else { warn(message); } } const value = Reflect.get(obj, prop, receiver); // since ServerResponse uses internal fields which // proxy can't map correctly we need to ensure functions // are bound correctly while being proxied if (typeof value === 'function') { return value.bind(obj); } return value; } }); } try { data = await getServerSideProps({ req: req, res: resOrProxy, query, resolvedUrl: renderOpts.resolvedUrl, ...pageIsDynamic ? { params: params } : undefined, ...previewData !== false ? { preview: true, previewData: previewData } : undefined, locales: renderOpts.locales, locale: renderOpts.locale, defaultLocale: renderOpts.defaultLocale }); canAccessRes = false; } catch (serverSidePropsError) { // remove not found error code to prevent triggering legacy // 404 rendering if ((0, _isError).default(serverSidePropsError) && serverSidePropsError.code === 'ENOENT') { delete serverSidePropsError.code; } throw serverSidePropsError; } if (data == null) { throw new Error(_constants.GSSP_NO_RETURNED_VALUE); } if (data.props instanceof Promise) { deferredContent = true; } const invalidKeys = Object.keys(data).filter((key)=>key !== 'props' && key !== 'redirect' && key !== 'notFound' ); if (data.unstable_notFound) { throw new Error(`unstable_notFound has been renamed to notFound, please update the field to continue. Page: ${pathname}`); } if (data.unstable_redirect) { throw new Error(`unstable_redirect has been renamed to redirect, please update the field to continue. Page: ${pathname}`); } if (invalidKeys.length) { throw new Error(invalidKeysMsg('getServerSideProps', invalidKeys)); } if ('notFound' in data && data.notFound) { if (pathname === '/404') { throw new Error(`The /404 page can not return notFound in "getStaticProps", please remove it to continue!`); } renderOpts.isNotFound = true; return null; } if ('redirect' in data && typeof data.redirect === 'object') { checkRedirectValues(data.redirect, req, 'getServerSideProps'); data.props = { __N_REDIRECT: data.redirect.destination, __N_REDIRECT_STATUS: (0, _loadCustomRoutes).getRedirectStatus(data.redirect) }; if (typeof data.redirect.basePath !== 'undefined') { data.props.__N_REDIRECT_BASE_PATH = data.redirect.basePath; } renderOpts.isRedirect = true; } if (deferredContent) { data.props = await data.props; } if ((dev || isBuildTimeSSG) && !(0, _isSerializableProps).isSerializableProps(pathname, 'getServerSideProps', data.props)) { // this fn should throw an error instead of ever returning `false` throw new Error('invariant: getServerSideProps did not return valid props. Please report this.'); } props1.pageProps = Object.assign({}, props1.pageProps, data.props); renderOpts.pageData = props1; } if (!isSSG && !getServerSideProps && process.env.NODE_ENV !== 'production' && Object.keys((props1 === null || props1 === void 0 ? void 0 : props1.pageProps) || {}).includes('url')) { console.warn(`The prop \`url\` is a reserved prop in Next.js for legacy reasons and will be overridden on page ${pathname}\n` + `See more info here: https://nextjs.org/docs/messages/reserved-page-prop`); } // Avoid rendering page un-necessarily for getServerSideProps data request // and getServerSideProps/getStaticProps redirects if (isDataReq && !isSSG || renderOpts.isRedirect) { // For server components, we still need to render the page to get the flight // data. if (!serverComponentsPageDataTransformStream) { return _renderResult.default.fromStatic(JSON.stringify(props1)); } } // We don't call getStaticProps or getServerSideProps while generating // the fallback so make sure to set pageProps to an empty object if (isFallback) { props1.pageProps = {}; } // Pass router to the Server Component as a temporary workaround. if (isServerComponent) { props1.pageProps = Object.assign({}, props1.pageProps); } // the response might be finished on the getInitialProps call if ((0, _utils).isResSent(res) && !isSSG) return null; if (renderServerComponentData) { return new _renderResult.default((0, _writerBrowserServer).renderToReadableStream(renderFlight(AppMod, ComponentMod, { ...props1.pageProps, ...serverComponentProps }), serverComponentManifest).pipeThrough((0, _nodeWebStreamsHelper).createBufferedTransformStream())); } // we preload the buildManifest for auto-export dynamic pages // to speed up hydrating query values let filteredBuildManifest = buildManifest; if (isAutoExport && pageIsDynamic) { const page = (0, _denormalizePagePath).denormalizePagePath((0, _normalizePagePath).normalizePagePath(pathname)); // This code would be much cleaner using `immer` and directly pushing into // the result from `getPageFiles`, we could maybe consider that in the // future. if (page in filteredBuildManifest.pages) { filteredBuildManifest = { ...filteredBuildManifest, pages: { ...filteredBuildManifest.pages, [page]: [ ...filteredBuildManifest.pages[page], ...filteredBuildManifest.lowPriorityFiles.filter((f)=>f.includes('_buildManifest') ), ] }, lowPriorityFiles: filteredBuildManifest.lowPriorityFiles.filter((f)=>!f.includes('_buildManifest') ) }; } } const Body = ({ children })=>{ return inAmpMode ? children : /*#__PURE__*/ _react.default.createElement("div", { id: "__next" }, children); }; const ReactDOMServer = hasConcurrentFeatures ? require('react-dom/server.browser') : require('react-dom/server'); /** * 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 = supportsDynamicHTML !== true; const renderDocument = async ()=>{ // For `Document`, there are two cases that we don't support: // 1. Using `Document.getInitialProps` in the Edge runtime. // 2. Using the class component `Document` with concurrent features. const builtinDocument = Document.__next_internal_document; if (process.browser && Document.getInitialProps) { // In the Edge runtime, `Document.getInitialProps` isn't supported. // We throw an error here if it's customized. if (!builtinDocument) { throw new Error('`getInitialProps` in Document component is not supported with the Edge Runtime.'); } } if ((isServerComponent || process.browser) && Document.getInitialProps) { if (builtinDocument) { Document = builtinDocument; } else { throw new Error('`getInitialProps` in Document component is not supported with React Server Components.'); } } async function documentInitialProps() { const renderPage = (options = {})=>{ if (ctx.err && ErrorDebug) { const html = ReactDOMServer.renderToString(/*#__PURE__*/ _react.default.createElement(Body, null, /*#__PURE__*/ _react.default.createElement(ErrorDebug, { error: ctx.err }))); return { html, head: head1 }; } if (dev && (props1.router || props1.Component)) { throw new Error(`'router' and 'Component' can not be returned in getInitialProps from _app.js https://nextjs.org/docs/messages/cant-override-next-props`); } const { App: EnhancedApp , Component: EnhancedComponent } = enhanceComponents(options, App, Component); const html = ReactDOMServer.renderToString(/*#__PURE__*/ _react.default.createElement(Body, null, /*#__PURE__*/ _react.default.createElement(AppContainerWithIsomorphicFiberStructure, null, /*#__PURE__*/ _react.default.createElement(EnhancedApp, Object.assign({ Component: EnhancedComponent, router: router }, props1))))); return { html, head: head1 }; }; const documentCtx = { ...ctx, renderPage }; const docProps = await (0, _utils).loadGetInitialProps(Document, documentCtx); // the response might be finished on the getInitialProps call if ((0, _utils).isResSent(res) && !isSSG) return null; if (!docProps || typeof docProps.html !== 'string') { const message = `"${(0, _utils).getDisplayName(Document)}.getInitialProps()" should resolve to an object with a "html" prop set with a valid html string`; throw new Error(message); } return { docProps, documentCtx }; } const renderContent = ()=>{ return ctx.err && ErrorDebug ? /*#__PURE__*/ _react.default.createElement(Body, null, /*#__PURE__*/ _react.default.createElement(ErrorDebug, { error: ctx.err })) : /*#__PURE__*/ _react.default.createElement(Body, null, /*#__PURE__*/ _react.default.createElement(AppContainerWithIsomorphicFiberStructure, null, isServerComponent && !!AppMod.__next_rsc__ ? // _app.server.js is used. /*#__PURE__*/ _react.default.createElement(Component, Object.assign({}, props1.pageProps)) : /*#__PURE__*/ _react.default.createElement(App, Object.assign({}, props1, { Component: Component, router: router })))); }; if (!hasConcurrentFeatures) { if (Document.getInitialProps) { const documentInitialPropsRes = await documentInitialProps(); if (documentInitialPropsRes === null) return null; const { docProps , documentCtx } = documentInitialPropsRes; return { bodyResult: (suffix)=>(0, _nodeWebStreamsHelper).streamFromArray([ docProps.html, suffix ]) , documentElement: (htmlProps)=>/*#__PURE__*/ _react.default.createElement(Document, Object.assign({}, htmlProps, docProps)) , head: docProps.head, headTags: await headTags(documentCtx), styles: docProps.styles }; } else { const content = renderContent(); // for non-concurrent rendering we need to ensure App is rendered // before _document so that updateHead is called/collected before // rendering _document's head const result = ReactDOMServer.renderToString(content); const bodyResult = (suffix)=>(0, _nodeWebStreamsHelper).streamFromArray([ result, suffix ]) ; const styles = jsxStyleRegistry.styles(); jsxStyleRegistry.flush(); return { bodyResult, documentElement: ()=>Document() , head: head1, headTags: [], styles }; } } else { // We start rendering the shell earlier, before returning the head tags // to `documentResult`. const content = renderContent(); const renderStream = await (0, _nodeWebStreamsHelper).renderToInitialStream({ ReactDOMServer, element: content }); const bodyResult = async (suffix)=>{ // this must be called inside bodyResult so appWrappers is // up to date when `wrapApp` is called const flushEffectHandler = ()=>{ const allFlushEffects = [ styledJsxFlushEffect, ...flushEffects || [], ]; const flushed = ReactDOMServer.renderToString(/*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, allFlushEffects.map((flushEffect, i)=>/*#__PURE__*/ _react.default.createElement(_react.default.Fragment, { key: i }, flushEffect()) ))); return flushed; }; // Handle static data for server components. async function generateStaticFlightDataIfNeeded() { if (serverComponentsPageDataTransformStream) { // If it's a server component with the Node.js runtime, we also // statically generate the page data. let data = ''; const readable = serverComponentsPageDataTransformStream.readable; const reader = readable.getReader(); const textDecoder = new TextDecoder(); while(true){ const { done , value } = await reader.read(); if (done) { break; } data += (0, _nodeWebStreamsHelper).decodeText(value, textDecoder); } renderOpts.pageData = { ...renderOpts.pageData, __flight__: data }; return data; } } // @TODO: A potential improvement would be to reuse the inlined // data stream, or pass a callback inside as this doesn't need to // be streamed. // Do not use `await` here. generateStaticFlightDataIfNeeded(); return await (0, _nodeWebStreamsHelper).continueFromInitialStream({ renderStream, suffix, dataStream: serverComponentsInlinedTransformStream === null || serverComponentsInlinedTransformStream === void 0 ? void 0 : serverComponentsInlinedTransformStream.readable, generateStaticHTML: generateStaticHTML || !hasConcurrentFeatures, flushEffectHandler }); }; const hasDocumentGetInitialProps = !(isServerComponent || process.browser || !Document.getInitialProps); const documentInitialPropsRes = hasDocumentGetInitialProps ? await documentInitialProps() : {}; if (documentInitialPropsRes === null) return null; const { docProps } = documentInitialPropsRes || {}; const documentElement = ()=>{ if (isServerComponent || process.browser) { return Document(); } return(/*#__PURE__*/ _react.default.createElement(Document, Object.assign({}, htmlProps1, docProps))); }; let styles; if (hasDocumentGetInitialProps) { styles = docProps.styles; } else { styles = jsxStyleRegistry.styles(); jsxStyleRegistry.flush(); } return { bodyResult, documentElement, head: head1, headTags: [], styles }; } }; const documentResult = await renderDocument(); if (!documentResult) { return null; } const dynamicImportsIds = new Set(); const dynamicImports = new Set(); for (const mod of reactLoadableModules){ const manifestItem = reactLoadableManifest[mod]; if (manifestItem) { dynamicImportsIds.add(manifestItem.id); manifestItem.files.forEach((item)=>{ dynamicImports.add(item); }); } } const hybridAmp = ampState.hybrid; const docComponentsRendered = {}; const { assetPrefix , buildId , customServer , defaultLocale , disableOptimizedLoading , domainLocales , locale , locales , runtimeConfig , } = renderOpts; const htmlProps1 = { __NEXT_DATA__: { props: props1, page: pathname, query, buildId, assetPrefix: assetPrefix === '' ? undefined : assetPrefix, runtimeConfig, nextExport: nextExport === true ? true : undefined, autoExport: isAutoExport === true ? true : undefined, isFallback, dynamicIds: dynamicImportsIds.size === 0 ? undefined : Array.from(dynamicImportsIds), err: renderOpts.err ? serializeError(dev, renderOpts.err) : undefined, gsp: !!getStaticProps ? true : undefined, gssp: !!getServerSideProps ? true : undefined, rsc: isServerComponent ? true : undefined, customServer, gip: hasPageGetInitialProps ? true : undefined, appGip: !defaultAppGetInitialProps ? true : undefined, locale, locales, defaultLocale, domainLocales, isPreview: isPreview === true ? true : undefined, notFoundSrcPage: notFoundSrcPage && dev ? notFoundSrcPage : undefined }, buildManifest: filteredBuildManifest, docComponentsRendered, dangerousAsPath: router.asPath, canonicalBase: !renderOpts.ampPath && (0, _requestMeta).getRequestMeta(req, '__nextStrippedLocale') ? `${renderOpts.canonicalBase || ''}/${renderOpts.locale}` : renderOpts.canonicalBase, ampPath, inAmpMode, isDevelopment: !!dev, hybridAmp, dynamicImports: Array.from(dynamicImports), assetPrefix, // Only enabled in production as development mode has features relying on HMR (style injection for example) unstable_runtimeJS: process.env.NODE_ENV === 'production' ? pageConfig.unstable_runtimeJS : undefined, unstable_JsPreload: pageConfig.unstable_JsPreload, devOnlyCacheBusterQueryString, scriptLoader, locale, disableOptimizedLoading, head: documentResult.head, headTags: documentResult.headTags, styles: docume