From 5ce7a966cabfbf80bb6827ad1b46d8d0dc252b19 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 20 Jan 2022 01:25:52 +0100 Subject: [PATCH 1/5] move utils --- packages/next/build/entries.ts | 2 +- packages/next/build/index.ts | 3 +- .../next-middleware-ssr-loader/render.ts | 4 ++ .../loaders/next-serverless-loader/utils.ts | 19 +++++----- packages/next/export/index.ts | 3 +- packages/next/server/api-utils.ts | 6 ++- packages/next/server/base-http.ts | 1 + packages/next/server/base-server.ts | 23 ++---------- packages/next/server/config.ts | 6 --- packages/next/server/next-server.ts | 37 ++++++++++++++++--- packages/next/server/send-payload.ts | 5 ++- packages/next/server/utils.ts | 6 +++ 12 files changed, 69 insertions(+), 46 deletions(-) diff --git a/packages/next/build/entries.ts b/packages/next/build/entries.ts index 3779caae4ebbb..dab27b168dffc 100644 --- a/packages/next/build/entries.ts +++ b/packages/next/build/entries.ts @@ -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' diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index a1ea6bc2bcc22..89cc94663989c 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -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' diff --git a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts index a0f158e8587be..eaad9d55183a1 100644 --- a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts +++ b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts @@ -3,6 +3,8 @@ import { renderToHTML } from '../../../../server/web/render' import RenderResult from '../../../../server/render-result' import { toNodeHeaders } from '../../../../server/web/utils' +import Server from '../../../../server/base-server' + const createHeaders = (args?: any) => ({ ...args, 'x-middleware-ssr': '1', @@ -39,6 +41,8 @@ export function getRender({ restRenderOpts: any }) { return async function render(request: NextRequest) { + console.log(Server) + const { nextUrl: url, cookies, headers } = request const { pathname, searchParams } = url diff --git a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts index 28b1ce0953142..2ab3106b90c70 100644 --- a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts +++ b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts @@ -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' @@ -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' diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index 36b5d17e0317f..36d6930318ad4 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -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' diff --git a/packages/next/server/api-utils.ts b/packages/next/server/api-utils.ts index fab3277976969..a8bc956f4f6bf 100644 --- a/packages/next/server/api-utils.ts +++ b/packages/next/server/api-utils.ts @@ -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' @@ -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') { diff --git a/packages/next/server/base-http.ts b/packages/next/server/base-http.ts index b353df2d09683..e53d2ef811325 100644 --- a/packages/next/server/base-http.ts +++ b/packages/next/server/base-http.ts @@ -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, diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 4f91de8761e40..e8b4255f4d997 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -45,7 +45,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 { @@ -57,7 +57,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' @@ -280,6 +279,8 @@ export default abstract class Server { onWarning?: (warning: Error) => void }): Promise + protected abstract loadEnvConfig(params: { dev: boolean }): void + public constructor({ dir = '.', quiet = false, @@ -292,7 +293,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 @@ -382,22 +383,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 { diff --git a/packages/next/server/config.ts b/packages/next/server/config.ts index 01f6b902027f4..5018536b06388 100644 --- a/packages/next/server/config.ts +++ b/packages/next/server/config.ts @@ -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'] ) { diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index ed5476af2b5b9..192f747202f2f 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -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 } from 'path' @@ -44,6 +46,7 @@ import { ParsedUrl } from '../shared/lib/router/utils/parse-url' import * as Log from '../build/output/log' import BaseServer, { + Options, FindComponentsResult, prepareServerlessUrl, stringifyQuery, @@ -60,6 +63,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' @@ -78,11 +82,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')) } diff --git a/packages/next/server/send-payload.ts b/packages/next/server/send-payload.ts index 138e154080ad3..ccc702b69e1c7 100644 --- a/packages/next/server/send-payload.ts +++ b/packages/next/server/send-payload.ts @@ -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 } diff --git a/packages/next/server/utils.ts b/packages/next/server/utils.ts index e9e4cb9a66e2d..2448f8d399eff 100644 --- a/packages/next/server/utils.ts +++ b/packages/next/server/utils.ts @@ -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 +} From 8eb67b381eac2f7badcba184c22d466bc5d6bbc6 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 20 Jan 2022 16:18:36 +0100 Subject: [PATCH 2/5] pipe chalk to console.log in the web runtime --- packages/next/build/output/log.ts | 2 +- packages/next/lib/chalk.ts | 9 +++++++++ packages/next/lib/load-custom-routes.ts | 2 +- packages/next/lib/web/chalk.ts | 19 +++++++++++++++++++ packages/next/server/config.ts | 2 +- packages/next/server/lib/find-page-file.ts | 2 +- 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 packages/next/lib/chalk.ts create mode 100644 packages/next/lib/web/chalk.ts diff --git a/packages/next/build/output/log.ts b/packages/next/build/output/log.ts index 9bbe2d26117b5..9220fe1834e36 100644 --- a/packages/next/build/output/log.ts +++ b/packages/next/build/output/log.ts @@ -1,4 +1,4 @@ -import chalk from 'next/dist/compiled/chalk' +import chalk from '../../lib/chalk' export const prefixes = { wait: chalk.cyan('wait') + ' -', diff --git a/packages/next/lib/chalk.ts b/packages/next/lib/chalk.ts new file mode 100644 index 0000000000000..f25f56ec35224 --- /dev/null +++ b/packages/next/lib/chalk.ts @@ -0,0 +1,9 @@ +let chalk: typeof import('next/dist/compiled/chalk') + +if (!process.browser) { + chalk = require('next/dist/compiled/chalk') +} else { + chalk = require('./web/chalk').default +} + +export default chalk diff --git a/packages/next/lib/load-custom-routes.ts b/packages/next/lib/load-custom-routes.ts index 87765abc4267e..05afa09b9c94a 100644 --- a/packages/next/lib/load-custom-routes.ts +++ b/packages/next/lib/load-custom-routes.ts @@ -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' diff --git a/packages/next/lib/web/chalk.ts b/packages/next/lib/web/chalk.ts new file mode 100644 index 0000000000000..0d6e741a912d8 --- /dev/null +++ b/packages/next/lib/web/chalk.ts @@ -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') + +export default chalk diff --git a/packages/next/server/config.ts b/packages/next/server/config.ts index 5018536b06388..fd91abc117e1e 100644 --- a/packages/next/server/config.ts +++ b/packages/next/server/config.ts @@ -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' diff --git a/packages/next/server/lib/find-page-file.ts b/packages/next/server/lib/find-page-file.ts index 8baf2725ed12a..a8bb85406e6ac 100644 --- a/packages/next/server/lib/find-page-file.ts +++ b/packages/next/server/lib/find-page-file.ts @@ -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' From 9d12601f31303c68f7c6f64c3451613324c9a105 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 20 Jan 2022 16:19:27 +0100 Subject: [PATCH 3/5] remove testing code --- .../webpack/loaders/next-middleware-ssr-loader/render.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts index eaad9d55183a1..a0f158e8587be 100644 --- a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts +++ b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts @@ -3,8 +3,6 @@ import { renderToHTML } from '../../../../server/web/render' import RenderResult from '../../../../server/render-result' import { toNodeHeaders } from '../../../../server/web/utils' -import Server from '../../../../server/base-server' - const createHeaders = (args?: any) => ({ ...args, 'x-middleware-ssr': '1', @@ -41,8 +39,6 @@ export function getRender({ restRenderOpts: any }) { return async function render(request: NextRequest) { - console.log(Server) - const { nextUrl: url, cookies, headers } = request const { pathname, searchParams } = url From 806cf3d755eb4ec4abc0b5e82fcf15204b99fec1 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 20 Jan 2022 17:49:46 +0100 Subject: [PATCH 4/5] add typeof window define --- packages/next/build/webpack-config.ts | 1 + packages/next/lib/chalk.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index ddd269cac3b80..882a25fc0c641 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1400,6 +1400,7 @@ export default async function getBaseWebpackConfig( `, } : {}), + 'typeof window': JSON.stringify(isServer ? 'undefined' : 'object'), }), !isServer && new ReactLoadablePlugin({ diff --git a/packages/next/lib/chalk.ts b/packages/next/lib/chalk.ts index f25f56ec35224..d6150d2dcf3e9 100644 --- a/packages/next/lib/chalk.ts +++ b/packages/next/lib/chalk.ts @@ -1,6 +1,6 @@ let chalk: typeof import('next/dist/compiled/chalk') -if (!process.browser) { +if (typeof window === 'undefined') { chalk = require('next/dist/compiled/chalk') } else { chalk = require('./web/chalk').default From 95c7525d15111fd968a9f0c74b843176ce1ccc42 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 20 Jan 2022 20:30:01 +0100 Subject: [PATCH 5/5] fix webpack config --- packages/next/build/webpack-config.ts | 1 - packages/next/lib/web/chalk.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 882a25fc0c641..ddd269cac3b80 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1400,7 +1400,6 @@ export default async function getBaseWebpackConfig( `, } : {}), - 'typeof window': JSON.stringify(isServer ? 'undefined' : 'object'), }), !isServer && new ReactLoadablePlugin({ diff --git a/packages/next/lib/web/chalk.ts b/packages/next/lib/web/chalk.ts index 0d6e741a912d8..eb4be7f9bd5ea 100644 --- a/packages/next/lib/web/chalk.ts +++ b/packages/next/lib/web/chalk.ts @@ -5,7 +5,7 @@ // - chalk.bold.cyan('message') // - chalk.hex('#fff').underline('hello') const log = console.log -const chalk = new Proxy(log, { +const chalk: any = new Proxy(log, { get(_, prop: string) { if ( ['hex', 'rgb', 'ansi256', 'bgHex', 'bgRgb', 'bgAnsi256'].includes(prop) @@ -14,6 +14,6 @@ const chalk = new Proxy(log, { } return chalk }, -}) as typeof import('next/dist/compiled/chalk') +}) export default chalk