未验证 提交 51b9eabe 编写于 作者: J Joe Haddad 提交者: GitHub

Refactor server router (#7431)

* Format next server

* Extract findPageComponents logic from renderToHTMLWithComponents

* Apply a little formatting

* Lift up component loading
上级 77b23264
import {BUILD_MANIFEST, CLIENT_STATIC_FILES_PATH, REACT_LOADABLE_MANIFEST, SERVER_DIRECTORY, SERVERLESS_DIRECTORY} from '../lib/constants';
import { join } from 'path';
import {
BUILD_MANIFEST,
CLIENT_STATIC_FILES_PATH,
REACT_LOADABLE_MANIFEST,
SERVER_DIRECTORY,
} from '../lib/constants'
import { join } from 'path'
import { requirePage } from './require';
import { requirePage } from './require'
export function interopDefault(mod: any) {
return mod.default || mod
}
export async function loadComponents(distDir: string, buildId: string, pathname: string, serverless: boolean) {
export type LoadComponentsReturnType = {
Component: any
buildManifest?: any
reactLoadableManifest?: any
Document?: any
DocumentMiddleware?: any
App?: any,
}
export async function loadComponents(
distDir: string,
buildId: string,
pathname: string,
serverless: boolean,
): Promise<LoadComponentsReturnType> {
if (serverless) {
const Component = await requirePage(pathname, distDir, serverless)
return { Component }
}
const documentPath = join(distDir, SERVER_DIRECTORY, CLIENT_STATIC_FILES_PATH, buildId, 'pages', '_document')
const appPath = join(distDir, SERVER_DIRECTORY, CLIENT_STATIC_FILES_PATH, buildId, 'pages', '_app')
const documentPath = join(
distDir,
SERVER_DIRECTORY,
CLIENT_STATIC_FILES_PATH,
buildId,
'pages',
'_document',
)
const appPath = join(
distDir,
SERVER_DIRECTORY,
CLIENT_STATIC_FILES_PATH,
buildId,
'pages',
'_app',
)
const DocumentMod = require(documentPath)
const { middleware: DocumentMiddleware } = DocumentMod
const [buildManifest, reactLoadableManifest, Component, Document, App] = await Promise.all([
const [
buildManifest,
reactLoadableManifest,
Component,
Document,
App,
] = await Promise.all([
require(join(distDir, BUILD_MANIFEST)),
require(join(distDir, REACT_LOADABLE_MANIFEST)),
interopDefault(requirePage(pathname, distDir, serverless)),
......
......@@ -21,8 +21,12 @@ import {
PAGES_MANIFEST,
} from '../lib/constants'
import * as envConfig from '../lib/runtime-config'
import { loadComponents, interopDefault } from './load-components'
import { getPagePath } from './require';
import {
loadComponents,
interopDefault,
LoadComponentsReturnType,
} from './load-components'
import { getPagePath } from './require'
type NextConfig = any
......@@ -47,8 +51,8 @@ export default class Server {
buildId: string
generateEtags: boolean
runtimeConfig?: { [key: string]: any }
assetPrefix?: string,
autoExport: boolean,
assetPrefix?: string
autoExport: boolean
dev?: boolean,
}
router: Router
......@@ -237,7 +241,11 @@ export default class Server {
* @param res http response
* @param pathname path of request
*/
private async handleApiRequest(req: IncomingMessage, res: ServerResponse, pathname: string) {
private async handleApiRequest(
req: IncomingMessage,
res: ServerResponse,
pathname: string,
) {
const resolverFunction = await this.resolveApiRequest(pathname)
if (resolverFunction === null) {
res.statusCode = 404
......@@ -254,7 +262,11 @@ export default class Server {
* @param pathname path of request
*/
private resolveApiRequest(pathname: string) {
return getPagePath(pathname, this.distDir, this.nextConfig.target === 'serverless')
return getPagePath(
pathname,
this.distDir,
this.nextConfig.target === 'serverless',
)
}
private generatePublicRoutes(): Route[] {
......@@ -333,7 +345,11 @@ export default class Server {
}
const html = await this.renderToHTML(req, res, pathname, query, {
dataOnly: this.renderOpts.ampBindInitData && Boolean(query.dataOnly) || (req.headers && (req.headers.accept || '').indexOf('application/amp.bind+json') !== -1),
dataOnly:
(this.renderOpts.ampBindInitData && Boolean(query.dataOnly)) ||
(req.headers &&
(req.headers.accept || '').indexOf('application/amp.bind+json') !==
-1),
})
// Request was ended by the user
if (html === null) {
......@@ -343,32 +359,54 @@ export default class Server {
return this.sendHTML(req, res, html)
}
private async renderToHTMLWithComponents(
req: IncomingMessage,
res: ServerResponse,
private async findPageComponents(
pathname: string,
query: ParsedUrlQuery = {},
opts: any,
) {
const serverless = !this.renderOpts.dev && this.nextConfig.target === 'serverless'
const serverless =
!this.renderOpts.dev && this.nextConfig.target === 'serverless'
// try serving a static AMP version first
if (query.amp) {
try {
const result = await loadComponents(this.distDir, this.buildId, (pathname === '/' ? '/index' : pathname) + '.amp', serverless)
if (typeof result.Component === 'string') return result.Component
return await loadComponents(
this.distDir,
this.buildId,
(pathname === '/' ? '/index' : pathname) + '.amp',
serverless,
)
} catch (err) {
if (err.code !== 'ENOENT') throw err
}
}
const result = await loadComponents(this.distDir, this.buildId, pathname, serverless)
return await loadComponents(
this.distDir,
this.buildId,
pathname,
serverless,
)
}
private async renderToHTMLWithComponents(
req: IncomingMessage,
res: ServerResponse,
pathname: string,
query: ParsedUrlQuery = {},
result: LoadComponentsReturnType,
opts: any,
) {
// handle static page
if (typeof result.Component === 'string') return result.Component
if (typeof result.Component === 'string') {
return result.Component
}
// handle serverless
if (typeof result.Component === 'object' &&
if (
typeof result.Component === 'object' &&
typeof result.Component.renderReqToHTML === 'function'
) {
return result.Component.renderReqToHTML(req, res)
}
return renderToHTML(req, res, pathname, query, { ...result, ...opts })
}
......@@ -377,19 +415,25 @@ export default class Server {
res: ServerResponse,
pathname: string,
query: ParsedUrlQuery = {},
{ amphtml, dataOnly, hasAmp }: {
amphtml?: boolean,
hasAmp?: boolean,
{
amphtml,
dataOnly,
hasAmp,
}: {
amphtml?: boolean
hasAmp?: boolean
dataOnly?: boolean,
} = {},
): Promise<string | null> {
try {
// To make sure the try/catch is executed
const result = await this.findPageComponents(pathname, query)
const html = await this.renderToHTMLWithComponents(
req,
res,
pathname,
query,
result,
{ ...this.renderOpts, amphtml, hasAmp, dataOnly },
)
return html
......@@ -430,7 +474,8 @@ export default class Server {
_pathname: string,
query: ParsedUrlQuery = {},
) {
return this.renderToHTMLWithComponents(req, res, '/_error', query, {
const result = await this.findPageComponents('/_error', query)
return this.renderToHTMLWithComponents(req, res, '/_error', query, result, {
...this.renderOpts,
err,
})
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册