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