Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve type imports in server/render and optimize the Edge SSR loader #34552

Merged
merged 6 commits into from Feb 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -4,28 +4,13 @@ import type { BuildManifest } from '../../../../server/get-page-files'
import type { ReactLoadableManifest } from '../../../../server/load-components'

import { NextRequest } from '../../../../server/web/spec-extension/request'
import { toNodeHeaders } from '../../../../server/web/utils'

import WebServer from '../../../../server/web-server'
import {
WebNextRequest,
WebNextResponse,
} from '../../../../server/base-http/web'

const createHeaders = (args?: any) => ({
...args,
'x-middleware-ssr': '1',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
})

function sendError(req: any, error: Error) {
const defaultMessage = 'An error occurred while rendering ' + req.url + '.'
return new Response((error && error.message) || defaultMessage, {
status: 500,
headers: createHeaders(),
})
}

// Polyfilled for `path-browserify` inside the Web Server.
process.cwd = () => ''

Expand Down Expand Up @@ -123,31 +108,20 @@ export function getRender({
const requestHandler = server.getRequestHandler()

return async function render(request: NextRequest) {
const { nextUrl: url, cookies, headers } = request
const { pathname, searchParams } = url

const { nextUrl: url } = request
const { searchParams } = url
const query = Object.fromEntries(searchParams)
const req = {
url: pathname,
cookies,
headers: toNodeHeaders(headers),
}

// Preflight request
if (request.method === 'HEAD') {
// Hint the client that the matched route is a SSR page.
return new Response(null, {
headers: createHeaders(),
headers: {
'x-middleware-ssr': '1',
},
})
}

// @TODO: We should move this into server/render.
if (Document.getInitialProps) {
const err = new Error(
'`getInitialProps` in Document component is not supported with the Edge Runtime.'
)
return sendError(req, err)
}

const renderServerComponentData = isServerComponent
? query.__flight__ !== undefined
: false
Expand Down
4 changes: 3 additions & 1 deletion packages/next/server/dev/hot-reloader.ts
Expand Up @@ -336,6 +336,8 @@ export default class HotReloader {
)
)

const hasEdgeRuntimePages = this.runtime === 'edge'

return webpackConfigSpan
.traceChild('generate-webpack-config')
.traceAsyncFn(() =>
Expand Down Expand Up @@ -363,7 +365,7 @@ export default class HotReloader {
}),
// For the edge runtime, we need an extra compiler to generate the
// web-targeted server bundle for now.
this.runtime === 'edge'
hasEdgeRuntimePages
? getBaseWebpackConfig(this.dir, {
dev: true,
isServer: true,
Expand Down
56 changes: 32 additions & 24 deletions packages/next/server/render.tsx
@@ -1,10 +1,29 @@
import { IncomingMessage, ServerResponse } from 'http'
import { ParsedUrlQuery, stringify as stringifyQuery } from 'querystring'
import type { IncomingMessage, ServerResponse } from 'http'
import type { NextRouter } from '../shared/lib/router/router'
import type { HtmlProps } from '../shared/lib/html-context'
import type { DomainLocale } from './config'
import type {
AppType,
DocumentInitialProps,
DocumentProps,
DocumentContext,
NextComponentType,
RenderPage,
RenderPageResult,
} from '../shared/lib/utils'
import type { ImageConfigComplete } from './image-config'
import type { Redirect } from '../lib/load-custom-routes'
import type { NextApiRequestCookies, __ApiPreviewProps } from './api-utils'
import type { FontManifest } from './font-utils'
import type { LoadComponentsReturnType, ManifestItem } from './load-components'
import type { GetServerSideProps, GetStaticProps, PreviewData } from '../types'
import type { UnwrapPromise } from '../lib/coalesced-function'

import React from 'react'
import { ParsedUrlQuery, stringify as stringifyQuery } from 'querystring'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack'
import { renderToReadableStream } from 'next/dist/compiled/react-server-dom-webpack/writer.browser.server'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
import { UnwrapPromise } from '../lib/coalesced-function'
import {
GSP_NO_RETURNED_VALUE,
GSSP_COMPONENT_MEMBER_ERROR,
Expand All @@ -15,56 +34,38 @@ import {
SSG_GET_INITIAL_PROPS_CONFLICT,
UNSTABLE_REVALIDATE_RENAME_ERROR,
} from '../lib/constants'
import { isSerializableProps } from '../lib/is-serializable-props'
import { GetServerSideProps, GetStaticProps, PreviewData } from '../types'
import { isInAmpMode } from '../shared/lib/amp'
import { AmpStateContext } from '../shared/lib/amp-context'
import {
SERVER_PROPS_ID,
STATIC_PROPS_ID,
STATIC_STATUS_PAGES,
} from '../shared/lib/constants'
import { isSerializableProps } from '../lib/is-serializable-props'
import { isInAmpMode } from '../shared/lib/amp'
import { AmpStateContext } from '../shared/lib/amp-context'
import { defaultHead } from '../shared/lib/head'
import { HeadManagerContext } from '../shared/lib/head-manager-context'
import Loadable from '../shared/lib/loadable'
import { LoadableContext } from '../shared/lib/loadable-context'
import { RouterContext } from '../shared/lib/router-context'
import { NextRouter } from '../shared/lib/router/router'
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
import {
AppType,
ComponentsEnhancer,
DocumentInitialProps,
DocumentProps,
DocumentContext,
getDisplayName,
isResSent,
loadGetInitialProps,
NextComponentType,
RenderPage,
RenderPageResult,
} from '../shared/lib/utils'

import { HtmlContext } from '../shared/lib/html-context'
import type { HtmlProps } from '../shared/lib/html-context'

import type { NextApiRequestCookies, __ApiPreviewProps } from './api-utils'
import { denormalizePagePath } from './denormalize-page-path'
import type { FontManifest } from './font-utils'
import type { LoadComponentsReturnType, ManifestItem } from './load-components'
import { normalizePagePath } from './normalize-page-path'
import { getRequestMeta, NextParsedUrlQuery } from './request-meta'
import {
allowedStatusCodes,
getRedirectStatus,
Redirect,
} from '../lib/load-custom-routes'
import { DomainLocale } from './config'
import RenderResult from './render-result'
import isError from '../lib/is-error'
import { readableStreamTee } from './web/utils'
import { ImageConfigContext } from '../shared/lib/image-config-context'
import { ImageConfigComplete } from './image-config'
import { FlushEffectsContext } from '../shared/lib/flush-effects'

let optimizeAmp: typeof import('./optimize-amp').default
Expand Down Expand Up @@ -1248,6 +1249,13 @@ export async function renderToHTML(
*/
const generateStaticHTML = supportsDynamicHTML !== true
const renderDocument = async () => {
if (runtime === 'edge' && Document.getInitialProps) {
// In the Edge runtime, Document.getInitialProps isn't supported.
throw new Error(
'`getInitialProps` in Document component is not supported with the Edge Runtime.'
)
}

if (!runtime && Document.getInitialProps) {
const renderPage: RenderPage = (
options: ComponentsEnhancer = {}
Expand Down
Expand Up @@ -247,12 +247,7 @@ const documentSuite = {
runTests: (context) => {
it('should error when custom _document has getInitialProps method', async () => {
const res = await fetchViaHTTP(context.appPort, '/')
const html = await res.text()

expect(res.status).toBe(500)
expect(html).toContain(
'`getInitialProps` in Document component is not supported with the Edge Runtime.'
)
})
},
beforeAll: () => documentPage.write(documentWithGip),
Expand Down