未验证 提交 44e40d4f 编写于 作者: G Gerald Monaco 提交者: GitHub

Clean up async in next-server (#10476)

* Clean up async in next-server

* fix case when err is null

* Refactor how components are loaded
Co-authored-by: NJoe Haddad <timer150@gmail.com>
上级 3e7cfd1f
...@@ -70,6 +70,11 @@ type Middleware = ( ...@@ -70,6 +70,11 @@ type Middleware = (
next: (err?: Error) => void next: (err?: Error) => void
) => void ) => void
type FindComponentsResult = {
components: LoadComponentsReturnType
query: ParsedUrlQuery
}
export type ServerConstructor = { export type ServerConstructor = {
/** /**
* Where the Next project is located - @default '.' * Where the Next project is located - @default '.'
...@@ -228,7 +233,7 @@ export default class Server { ...@@ -228,7 +233,7 @@ export default class Server {
console.error(err) console.error(err)
} }
private handleRequest( private async handleRequest(
req: IncomingMessage, req: IncomingMessage,
res: ServerResponse, res: ServerResponse,
parsedUrl?: UrlWithParsedQuery parsedUrl?: UrlWithParsedQuery
...@@ -255,11 +260,13 @@ export default class Server { ...@@ -255,11 +260,13 @@ export default class Server {
} }
res.statusCode = 200 res.statusCode = 200
return this.run(req, res, parsedUrl).catch(err => { try {
return await this.run(req, res, parsedUrl)
} catch (err) {
this.logError(err) this.logError(err)
res.statusCode = 500 res.statusCode = 500
res.end('Internal Server Error') res.end('Internal Server Error')
}) }
} }
public getRequestHandler() { public getRequestHandler() {
...@@ -780,28 +787,36 @@ export default class Server { ...@@ -780,28 +787,36 @@ export default class Server {
private async findPageComponents( private async findPageComponents(
pathname: string, pathname: string,
query: ParsedUrlQuery = {} query: ParsedUrlQuery = {},
) { params: Params | null = null
const serverless = !this.renderOpts.dev && this._isLikeServerless ): Promise<FindComponentsResult | null> {
const paths = [
// try serving a static AMP version first // try serving a static AMP version first
if (query.amp) { query.amp ? normalizePagePath(pathname) + '.amp' : null,
pathname,
].filter(Boolean)
for (const pagePath of paths) {
try { try {
return await loadComponents( const components = await loadComponents(
this.distDir, this.distDir,
this.buildId, this.buildId,
normalizePagePath(pathname) + '.amp', pagePath!,
serverless !this.renderOpts.dev && this._isLikeServerless
) )
return {
components,
query: {
...(components.unstable_getStaticProps
? { _nextDataReq: query._nextDataReq }
: query),
...(params || {}),
},
}
} catch (err) { } catch (err) {
if (err.code !== 'ENOENT') throw err if (err.code !== 'ENOENT') throw err
} }
} }
return await loadComponents( return null
this.distDir,
this.buildId,
pathname,
serverless
)
} }
private __sendPayload( private __sendPayload(
...@@ -847,8 +862,7 @@ export default class Server { ...@@ -847,8 +862,7 @@ export default class Server {
req: IncomingMessage, req: IncomingMessage,
res: ServerResponse, res: ServerResponse,
pathname: string, pathname: string,
query: ParsedUrlQuery = {}, { components, query }: FindComponentsResult,
result: LoadComponentsReturnType,
opts: any opts: any
): Promise<string | null> { ): Promise<string | null> {
// we need to ensure the status code if /404 is visited directly // we need to ensure the status code if /404 is visited directly
...@@ -857,16 +871,16 @@ export default class Server { ...@@ -857,16 +871,16 @@ export default class Server {
} }
// handle static page // handle static page
if (typeof result.Component === 'string') { if (typeof components.Component === 'string') {
return result.Component return components.Component
} }
// check request state // check request state
const isLikeServerless = const isLikeServerless =
typeof result.Component === 'object' && typeof components.Component === 'object' &&
typeof (result.Component as any).renderReqToHTML === 'function' typeof (components.Component as any).renderReqToHTML === 'function'
const isSSG = !!result.unstable_getStaticProps const isSSG = !!components.unstable_getStaticProps
const isServerProps = !!result.unstable_getServerProps const isServerProps = !!components.unstable_getServerProps
// Toggle whether or not this is a Data request // Toggle whether or not this is a Data request
const isDataReq = query._nextDataReq const isDataReq = query._nextDataReq
...@@ -888,7 +902,7 @@ export default class Server { ...@@ -888,7 +902,7 @@ export default class Server {
// handle serverless // handle serverless
if (isLikeServerless) { if (isLikeServerless) {
if (isDataReq) { if (isDataReq) {
const renderResult = await (result.Component as any).renderReqToHTML( const renderResult = await (components.Component as any).renderReqToHTML(
req, req,
res, res,
true true
...@@ -903,12 +917,12 @@ export default class Server { ...@@ -903,12 +917,12 @@ export default class Server {
return null return null
} }
this.prepareServerlessUrl(req, query) this.prepareServerlessUrl(req, query)
return (result.Component as any).renderReqToHTML(req, res) return (components.Component as any).renderReqToHTML(req, res)
} }
if (isDataReq && isServerProps) { if (isDataReq && isServerProps) {
const props = await renderToHTML(req, res, pathname, query, { const props = await renderToHTML(req, res, pathname, query, {
...result, ...components,
...opts, ...opts,
isDataReq, isDataReq,
}) })
...@@ -917,7 +931,7 @@ export default class Server { ...@@ -917,7 +931,7 @@ export default class Server {
} }
return renderToHTML(req, res, pathname, query, { return renderToHTML(req, res, pathname, query, {
...result, ...components,
...opts, ...opts,
}) })
} }
...@@ -968,7 +982,7 @@ export default class Server { ...@@ -968,7 +982,7 @@ export default class Server {
let renderResult let renderResult
// handle serverless // handle serverless
if (isLikeServerless) { if (isLikeServerless) {
renderResult = await (result.Component as any).renderReqToHTML( renderResult = await (components.Component as any).renderReqToHTML(
req, req,
res, res,
true true
...@@ -979,7 +993,7 @@ export default class Server { ...@@ -979,7 +993,7 @@ export default class Server {
sprRevalidate = renderResult.renderOpts.revalidate sprRevalidate = renderResult.renderOpts.revalidate
} else { } else {
const renderOpts = { const renderOpts = {
...result, ...components,
...opts, ...opts,
} }
renderResult = await renderToHTML(req, res, pathname, query, renderOpts) renderResult = await renderToHTML(req, res, pathname, query, renderOpts)
...@@ -1031,10 +1045,10 @@ export default class Server { ...@@ -1031,10 +1045,10 @@ export default class Server {
query.__nextFallback = 'true' query.__nextFallback = 'true'
if (isLikeServerless) { if (isLikeServerless) {
this.prepareServerlessUrl(req, query) this.prepareServerlessUrl(req, query)
html = await (result.Component as any).renderReqToHTML(req, res) html = await (components.Component as any).renderReqToHTML(req, res)
} else { } else {
html = (await renderToHTML(req, res, pathname, query, { html = (await renderToHTML(req, res, pathname, query, {
...result, ...components,
...opts, ...opts,
})) as string })) as string
} }
...@@ -1043,9 +1057,10 @@ export default class Server { ...@@ -1043,9 +1057,10 @@ export default class Server {
this.__sendPayload(res, html, 'text/html; charset=utf-8') this.__sendPayload(res, html, 'text/html; charset=utf-8')
} }
return doRender(ssgCacheKey, []).then( const {
async ({ isOrigin, value: { html, pageData, sprRevalidate } }) => { isOrigin,
// Respond to the request if a payload wasn't sent above (from cache) value: { html, pageData, sprRevalidate },
} = await doRender(ssgCacheKey, [])
if (!isResSent(res)) { if (!isResSent(res)) {
this.__sendPayload( this.__sendPayload(
res, res,
...@@ -1059,20 +1074,14 @@ export default class Server { ...@@ -1059,20 +1074,14 @@ export default class Server {
if (isOrigin) { if (isOrigin) {
// Preview mode should not be stored in cache // Preview mode should not be stored in cache
if (!isPreviewMode) { if (!isPreviewMode) {
await setSprCache( await setSprCache(ssgCacheKey, { html: html!, pageData }, sprRevalidate)
ssgCacheKey,
{ html: html!, pageData },
sprRevalidate
)
} }
} }
return null return null
} }
)
}
public renderToHTML( public async renderToHTML(
req: IncomingMessage, req: IncomingMessage,
res: ServerResponse, res: ServerResponse,
pathname: string, pathname: string,
...@@ -1085,44 +1094,35 @@ export default class Server { ...@@ -1085,44 +1094,35 @@ export default class Server {
hasAmp?: boolean hasAmp?: boolean
} = {} } = {}
): Promise<string | null> { ): Promise<string | null> {
return this.findPageComponents(pathname, query) try {
.then( const result = await this.findPageComponents(pathname, query)
result => { if (result) {
return this.renderToHTMLWithComponents( return await this.renderToHTMLWithComponents(
req, req,
res, res,
pathname, pathname,
result.unstable_getStaticProps
? { _nextDataReq: query._nextDataReq }
: query,
result, result,
{ ...this.renderOpts, amphtml, hasAmp } { ...this.renderOpts, amphtml, hasAmp }
) )
},
err => {
if (err.code !== 'ENOENT' || !this.dynamicRoutes) {
return Promise.reject(err)
} }
if (this.dynamicRoutes) {
for (const dynamicRoute of this.dynamicRoutes) { for (const dynamicRoute of this.dynamicRoutes) {
const params = dynamicRoute.match(pathname) const params = dynamicRoute.match(pathname)
if (!params) { if (!params) {
continue continue
} }
return this.findPageComponents(dynamicRoute.page, query).then( const result = await this.findPageComponents(
result => { dynamicRoute.page,
return this.renderToHTMLWithComponents( query,
params
)
if (result) {
return await this.renderToHTMLWithComponents(
req, req,
res, res,
dynamicRoute.page, dynamicRoute.page,
// only add params for SPR enabled pages
{
...(result.unstable_getStaticProps
? { _nextDataReq: query._nextDataReq }
: query),
...params,
},
result, result,
{ {
...this.renderOpts, ...this.renderOpts,
...@@ -1132,22 +1132,16 @@ export default class Server { ...@@ -1132,22 +1132,16 @@ export default class Server {
} }
) )
} }
)
} }
return Promise.reject(err)
} }
) } catch (err) {
.catch(err => {
if (err && err.code === 'ENOENT') {
res.statusCode = 404
return this.renderErrorToHTML(null, req, res, pathname, query)
} else {
this.logError(err) this.logError(err)
res.statusCode = 500 res.statusCode = 500
return this.renderErrorToHTML(err, req, res, pathname, query) return await this.renderErrorToHTML(err, req, res, pathname, query)
} }
})
res.statusCode = 404
return await this.renderErrorToHTML(null, req, res, pathname, query)
} }
public async renderError( public async renderError(
...@@ -1175,7 +1169,7 @@ export default class Server { ...@@ -1175,7 +1169,7 @@ export default class Server {
_pathname: string, _pathname: string,
query: ParsedUrlQuery = {} query: ParsedUrlQuery = {}
) { ) {
let result: null | LoadComponentsReturnType = null let result: null | FindComponentsResult = null
const { static404, pages404 } = this.nextConfig.experimental const { static404, pages404 } = this.nextConfig.experimental
const is404 = res.statusCode === 404 const is404 = res.statusCode === 404
...@@ -1184,26 +1178,14 @@ export default class Server { ...@@ -1184,26 +1178,14 @@ export default class Server {
// use static 404 page if available and is 404 response // use static 404 page if available and is 404 response
if (is404) { if (is404) {
if (static404) { if (static404) {
try {
result = await this.findPageComponents('/_errors/404') result = await this.findPageComponents('/_errors/404')
} catch (err) {
if (err.code !== 'ENOENT') {
throw err
}
}
} }
// use 404 if /_errors/404 isn't available which occurs // use 404 if /_errors/404 isn't available which occurs
// during development and when _app has getInitialProps // during development and when _app has getInitialProps
if (!result && pages404) { if (!result && pages404) {
try {
result = await this.findPageComponents('/404') result = await this.findPageComponents('/404')
using404Page = true using404Page = result !== null
} catch (err) {
if (err.code !== 'ENOENT') {
throw err
}
}
} }
} }
...@@ -1217,8 +1199,7 @@ export default class Server { ...@@ -1217,8 +1199,7 @@ export default class Server {
req, req,
res, res,
using404Page ? '/404' : '/_error', using404Page ? '/404' : '/_error',
query, result!,
result,
{ {
...this.renderOpts, ...this.renderOpts,
err, err,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册