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

Refactor base server to remove native dependencies #33499

Merged
merged 7 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion packages/next/build/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { stringify } from 'querystring'
import { API_ROUTE, DOT_NEXT_ALIAS, PAGES_DIR_ALIAS } from '../lib/constants'
import { MIDDLEWARE_ROUTE } from '../lib/constants'
import { __ApiPreviewProps } from '../server/api-utils'
import { isTargetLikeServerless } from '../server/config'
import { isTargetLikeServerless } from '../server/utils'
import { normalizePagePath } from '../server/normalize-page-path'
import { warn } from './output/log'
import { MiddlewareLoaderOptions } from './webpack/loaders/next-middleware-loader'
Expand Down
3 changes: 2 additions & 1 deletion packages/next/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ import {
isDynamicRoute,
} from '../shared/lib/router/utils'
import { __ApiPreviewProps } from '../server/api-utils'
import loadConfig, { isTargetLikeServerless } from '../server/config'
import loadConfig from '../server/config'
import { isTargetLikeServerless } from '../server/utils'
import { BuildManifest } from '../server/get-page-files'
import { normalizePagePath } from '../server/normalize-page-path'
import { getPagePath } from '../server/require'
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/output/log.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chalk from 'next/dist/compiled/chalk'
import chalk from '../../lib/chalk'

export const prefixes = {
wait: chalk.cyan('wait') + ' -',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { IncomingMessage, ServerResponse } from 'http'
import type { IncomingMessage, ServerResponse } from 'http'
import type { Rewrite } from '../../../../lib/load-custom-routes'
import type { BuildManifest } from '../../../../server/get-page-files'
import type { NextConfig } from '../../../../server/config'
import type {
GetServerSideProps,
GetStaticPaths,
GetStaticProps,
} from '../../../../types'

import { format as formatUrl, UrlWithParsedQuery, parse as parseUrl } from 'url'
import { parse as parseQs, ParsedUrlQuery } from 'querystring'
import { Rewrite } from '../../../../lib/load-custom-routes'
import { normalizeLocalePath } from '../../../../shared/lib/i18n/normalize-locale-path'
import pathMatch from '../../../../shared/lib/router/utils/path-match'
import { getRouteRegex } from '../../../../shared/lib/router/utils/route-regex'
Expand All @@ -11,19 +19,12 @@ import {
prepareDestination,
} from '../../../../shared/lib/router/utils/prepare-destination'
import { __ApiPreviewProps } from '../../../../server/api-utils'
import { BuildManifest } from '../../../../server/get-page-files'
import {
GetServerSideProps,
GetStaticPaths,
GetStaticProps,
} from '../../../../types'
import { acceptLanguage } from '../../../../server/accept-header'
import { detectLocaleCookie } from '../../../../shared/lib/i18n/detect-locale-cookie'
import { detectDomainLocale } from '../../../../shared/lib/i18n/detect-domain-locale'
import { denormalizePagePath } from '../../../../server/denormalize-page-path'
import cookie from 'next/dist/compiled/cookie'
import { TEMPORARY_REDIRECT_STATUS } from '../../../../shared/lib/constants'
import { NextConfig } from '../../../../server/config'
import { addRequestMeta } from '../../../../server/request-meta'
import { BaseNextRequest } from '../../../../server/base-http'

Expand Down
3 changes: 2 additions & 1 deletion packages/next/export/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import {
SERVERLESS_DIRECTORY,
SERVER_DIRECTORY,
} from '../shared/lib/constants'
import loadConfig, { isTargetLikeServerless } from '../server/config'
import loadConfig from '../server/config'
import { isTargetLikeServerless } from '../server/utils'
import { NextConfigComplete } from '../server/config-shared'
import { eventCliSession } from '../telemetry/events'
import { hasNextSupport } from '../telemetry/ci-info'
Expand Down
9 changes: 9 additions & 0 deletions packages/next/lib/chalk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
let chalk: typeof import('next/dist/compiled/chalk')

if (!process.browser) {
shuding marked this conversation as resolved.
Show resolved Hide resolved
chalk = require('next/dist/compiled/chalk')
} else {
chalk = require('./web/chalk').default
}

export default chalk
2 changes: 1 addition & 1 deletion packages/next/lib/load-custom-routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { NextConfig } from '../server/config'

import chalk from 'next/dist/compiled/chalk'
import chalk from './chalk'
import { parse as parseUrl } from 'url'
import * as pathToRegexp from 'next/dist/compiled/path-to-regexp'
import { escapeStringRegexp } from '../shared/lib/escape-regexp'
Expand Down
19 changes: 19 additions & 0 deletions packages/next/lib/web/chalk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// In the web runtime, we create an alternative object that just outputs the
// message to the console without any styling. The same APIs are supported
// for compatibility:
// - chalk.red('error')
// - chalk.bold.cyan('message')
// - chalk.hex('#fff').underline('hello')
const log = console.log
const chalk = new Proxy(log, {
get(_, prop: string) {
if (
['hex', 'rgb', 'ansi256', 'bgHex', 'bgRgb', 'bgAnsi256'].includes(prop)
) {
return () => chalk
}
return chalk
},
}) as typeof import('next/dist/compiled/chalk')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type assertion must be avoided here. We should use type narrowing


export default chalk
6 changes: 4 additions & 2 deletions packages/next/server/api-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IncomingMessage, ServerResponse } from 'http'
import type { IncomingMessage, ServerResponse } from 'http'

import { parse } from 'next/dist/compiled/content-type'
import { CookieSerializeOptions } from 'next/dist/compiled/cookie'
import getRawBody from 'next/dist/compiled/raw-body'
import { PageConfig, PreviewData } from 'next/types'
import { Stream } from 'stream'
import { isResSent, NextApiRequest, NextApiResponse } from '../shared/lib/utils'
Expand Down Expand Up @@ -157,6 +157,8 @@ export async function parseBody(
let buffer

try {
const getRawBody =
require('next/dist/compiled/raw-body') as typeof import('next/dist/compiled/raw-body')
buffer = await getRawBody(req, { encoding, limit })
} catch (e) {
if (isError(e) && e.type === 'entity.too.large') {
Expand Down
1 change: 1 addition & 0 deletions packages/next/server/base-http.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ServerResponse, IncomingMessage, IncomingHttpHeaders } from 'http'
import type { Writable, Readable } from 'stream'

import { PERMANENT_REDIRECT_STATUS } from '../shared/lib/constants'
import {
getCookieParser,
Expand Down
23 changes: 4 additions & 19 deletions packages/next/server/base-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
import * as envConfig from '../shared/lib/runtime-config'
import { DecodeError, normalizeRepeatedSlashes } from '../shared/lib/utils'
import { setLazyProp, getCookieParser, tryGetPreviewData } from './api-utils'
import { isTargetLikeServerless } from './config'
import { isTargetLikeServerless } from './utils'
import pathMatch from '../shared/lib/router/utils/path-match'
import Router, { replaceBasePath, route } from './router'
import {
Expand All @@ -55,7 +55,6 @@ import { IncrementalCache } from './incremental-cache'
import { execOnce } from '../shared/lib/utils'
import { isBlockedPage, isBot } from './utils'
import RenderResult from './render-result'
import { loadEnvConfig } from '@next/env'
import { removePathTrailingSlash } from '../client/normalize-trailing-slash'
import getRouteFromAssetPath from '../shared/lib/router/utils/get-route-from-asset-path'
import { denormalizePagePath } from './denormalize-page-path'
Expand Down Expand Up @@ -274,6 +273,8 @@ export default abstract class Server {
onWarning?: (warning: Error) => void
}): Promise<FetchEventResult | null>

protected abstract loadEnvConfig(params: { dev: boolean }): void

public constructor({
dir = '.',
quiet = false,
Expand All @@ -286,7 +287,7 @@ export default abstract class Server {
}: Options) {
this.dir = resolve(dir)
this.quiet = quiet
loadEnvConfig(this.dir, dev, Log)
this.loadEnvConfig({ dev })

// TODO: should conf be normalized to prevent missing
// values from causing issues as this can be user provided
Expand Down Expand Up @@ -376,22 +377,6 @@ export default abstract class Server {
flushToDisk: !minimalMode && this.nextConfig.experimental.isrFlushToDisk,
})
this.responseCache = new ResponseCache(this.incrementalCache)

/**
* This sets environment variable to be used at the time of SSR by head.tsx.
* Using this from process.env allows targeting both serverless and SSR by calling
* `process.env.__NEXT_OPTIMIZE_IMAGES`.
* TODO(atcastle@): Remove this when experimental.optimizeImages are being cleaned up.
*/
if (this.renderOpts.optimizeFonts) {
process.env.__NEXT_OPTIMIZE_FONTS = JSON.stringify(true)
}
if (this.renderOpts.optimizeImages) {
process.env.__NEXT_OPTIMIZE_IMAGES = JSON.stringify(true)
}
if (this.renderOpts.optimizeCss) {
process.env.__NEXT_OPTIMIZE_CSS = JSON.stringify(true)
}
}

public logError(err: Error): void {
Expand Down
8 changes: 1 addition & 7 deletions packages/next/server/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chalk from 'next/dist/compiled/chalk'
import chalk from '../lib/chalk'
import findUp from 'next/dist/compiled/find-up'
import { basename, extname, relative, isAbsolute, resolve } from 'path'
import { pathToFileURL } from 'url'
Expand Down Expand Up @@ -656,12 +656,6 @@ export default async function loadConfig(
return completeConfig
}

export function isTargetLikeServerless(target: string) {
const isServerless = target === 'serverless'
const isServerlessTrace = target === 'experimental-serverless-trace'
return isServerless || isServerlessTrace
}

export function setHttpAgentOptions(
options: NextConfigComplete['httpAgentOptions']
) {
Expand Down
2 changes: 1 addition & 1 deletion packages/next/server/lib/find-page-file.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { join, sep as pathSeparator, normalize } from 'path'
import chalk from 'next/dist/compiled/chalk'
import chalk from '../../lib/chalk'
import { warn } from '../../build/output/log'
import { promises } from 'fs'
import { denormalizePagePath } from '../normalize-page-path'
Expand Down
37 changes: 32 additions & 5 deletions packages/next/server/next-server.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { Params, Route } from './router'
import { CacheFs, execOnce } from '../shared/lib/utils'
import type { CacheFs } from '../shared/lib/utils'
import type { MiddlewareManifest } from '../build/webpack/plugins/middleware-plugin'
import type RenderResult from './render-result'
import type { FetchEventResult } from './web/types'
import type { ParsedNextUrl } from '../shared/lib/router/utils/parse-next-url'

import { execOnce } from '../shared/lib/utils'
import {
addRequestMeta,
getRequestMeta,
NextParsedUrlQuery,
NextUrlWithParsedQuery,
} from './request-meta'
import type { MiddlewareManifest } from '../build/webpack/plugins/middleware-plugin'
import type RenderResult from './render-result'
import type { FetchEventResult } from './web/types'
import type { ParsedNextUrl } from '../shared/lib/router/utils/parse-next-url'

import fs from 'fs'
import { join, relative, resolve, sep } from 'path'
Expand Down Expand Up @@ -46,6 +48,7 @@ import { ParsedUrl } from '../shared/lib/router/utils/parse-url'
import * as Log from '../build/output/log'

import BaseServer, {
Options,
FindComponentsResult,
prepareServerlessUrl,
stringifyQuery,
Expand All @@ -62,6 +65,7 @@ import { prepareDestination } from '../shared/lib/router/utils/prepare-destinati
import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path'
import { getMiddlewareRegex, getRouteMatcher } from '../shared/lib/router/utils'
import { MIDDLEWARE_ROUTE } from '../lib/constants'
import { loadEnvConfig } from '@next/env'

export * from './base-server'

Expand All @@ -80,11 +84,34 @@ export interface NodeRequestHandler {
}

export default class NextNodeServer extends BaseServer {
constructor(options: Options) {
super(options)
/**
* This sets environment variable to be used at the time of SSR by head.tsx.
* Using this from process.env allows targeting both serverless and SSR by calling
* `process.env.__NEXT_OPTIMIZE_IMAGES`.
* TODO(atcastle@): Remove this when experimental.optimizeImages are being cleaned up.
*/
if (this.renderOpts.optimizeFonts) {
process.env.__NEXT_OPTIMIZE_FONTS = JSON.stringify(true)
}
if (this.renderOpts.optimizeImages) {
process.env.__NEXT_OPTIMIZE_IMAGES = JSON.stringify(true)
}
if (this.renderOpts.optimizeCss) {
process.env.__NEXT_OPTIMIZE_CSS = JSON.stringify(true)
}
}

private compression =
this.nextConfig.compress && this.nextConfig.target === 'server'
? (compression() as ExpressMiddleware)
: undefined

protected loadEnvConfig({ dev }: { dev: boolean }) {
loadEnvConfig(this.dir, dev, Log)
}

protected getHasStaticDir(): boolean {
return fs.existsSync(join(this.dir, 'static'))
}
Expand Down
5 changes: 3 additions & 2 deletions packages/next/server/send-payload.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { IncomingMessage, ServerResponse } from 'http'
import type { IncomingMessage, ServerResponse } from 'http'
import type { BaseNextResponse } from './base-http'

import { isResSent } from '../shared/lib/utils'
import generateETag from 'next/dist/compiled/etag'
import fresh from 'next/dist/compiled/fresh'
import RenderResult from './render-result'
import { BaseNextResponse } from './base-http'

export type PayloadOptions =
| { private: true }
Expand Down
6 changes: 6 additions & 0 deletions packages/next/server/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ export function isBot(userAgent: string): boolean {
userAgent
)
}

export function isTargetLikeServerless(target: string) {
const isServerless = target === 'serverless'
const isServerlessTrace = target === 'experimental-serverless-trace'
return isServerless || isServerlessTrace
}