From 293ff35484ccfdff6eae18acc14225b6bfd1f0d6 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 20 Apr 2022 13:24:01 +0200 Subject: [PATCH] Decouple nodejs path dependency from base server --- packages/next/lib/constants.ts | 5 ++++- packages/next/server/base-server.ts | 17 +++++++---------- packages/next/server/incremental-cache.ts | 2 +- packages/next/server/next-server.ts | 16 ++++++++++++++++ packages/next/server/normalize-page-path.ts | 4 +++- packages/next/server/render.tsx | 5 +++-- packages/next/server/web-server.ts | 14 +++++++++++++- packages/next/shared/lib/fallback/path.ts | 5 +++++ .../next/shared/lib/router/utils/querystring.ts | 2 +- packages/next/types/misc.d.ts | 5 +++++ test/integration/react-18/app/pages/index.js | 4 ++++ test/integration/react-18/test/index.test.js | 3 +++ 12 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 packages/next/shared/lib/fallback/path.ts diff --git a/packages/next/lib/constants.ts b/packages/next/lib/constants.ts index 77b438810519..7af82942bcbb 100644 --- a/packages/next/lib/constants.ts +++ b/packages/next/lib/constants.ts @@ -1,4 +1,7 @@ -import { join } from 'path' +import path from '../shared/lib/fallback/path' + +const { join } = path + export const NEXT_PROJECT_ROOT = join(__dirname, '..', '..') export const NEXT_PROJECT_ROOT_DIST = join(NEXT_PROJECT_ROOT, 'dist') export const NEXT_PROJECT_ROOT_NODE_MODULES = join( diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 2e1f835e2706..8cdf94df1a0a 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -18,13 +18,10 @@ import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plug import type { BaseNextRequest, BaseNextResponse } from './base-http' import type { PayloadOptions } from './send-payload' -import { join, resolve } from 'path' import { parse as parseQs } from 'querystring' import { format as formatUrl, parse as parseUrl } from 'url' import { getRedirectStatus } from '../lib/load-custom-routes' import { - SERVERLESS_DIRECTORY, - SERVER_DIRECTORY, STATIC_STATUS_PAGES, TEMPORARY_REDIRECT_STATUS, } from '../shared/lib/constants' @@ -182,6 +179,9 @@ export default abstract class Server { public readonly hostname?: string public readonly port?: number + protected abstract getDir(_dir: string): string + protected abstract getDistDir(): string + protected abstract getPagesDir(): string protected abstract getPublicDir(): string protected abstract getHasStaticDir(): boolean protected abstract getPagesManifest(): PagesManifest | undefined @@ -271,7 +271,7 @@ export default abstract class Server { hostname, port, }: Options) { - this.dir = resolve(dir) + this.dir = this.getDir(dir) this.quiet = quiet this.loadEnvConfig({ dev }) @@ -280,7 +280,7 @@ export default abstract class Server { this.nextConfig = conf as NextConfigComplete this.hostname = hostname this.port = port - this.distDir = join(this.dir, this.nextConfig.distDir) + this.distDir = this.getDistDir() this.publicDir = this.getPublicDir() this.hasStaticDir = !minimalMode && this.getHasStaticDir() @@ -350,15 +350,12 @@ export default abstract class Server { this.router = new Router(this.generateRoutes()) this.setAssetPrefix(assetPrefix) + const pagesDir = this.getPagesDir() this.incrementalCache = new IncrementalCache({ fs: this.getCacheFilesystem(), dev, distDir: this.distDir, - pagesDir: join( - this.distDir, - this._isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY, - 'pages' - ), + pagesDir, locales: this.nextConfig.i18n?.locales, max: this.nextConfig.experimental.isrMemoryCacheSize, flushToDisk: !minimalMode && this.nextConfig.experimental.isrFlushToDisk, diff --git a/packages/next/server/incremental-cache.ts b/packages/next/server/incremental-cache.ts index 7b4b1a8ad6e9..d1d463fba2e2 100644 --- a/packages/next/server/incremental-cache.ts +++ b/packages/next/server/incremental-cache.ts @@ -1,7 +1,7 @@ import type { CacheFs } from '../shared/lib/utils' import LRUCache from 'next/dist/compiled/lru-cache' -import path from 'path' +import path from '../shared/lib/fallback/path' import { PrerenderManifest } from '../build' import { normalizePagePath } from './normalize-page-path' import { IncrementalCacheValue, IncrementalCacheEntry } from './response-cache' diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 2291f6514f08..44e21238694e 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -147,10 +147,26 @@ export default class NextNodeServer extends BaseServer { loadEnvConfig(this.dir, dev, Log) } + protected getDir(_dir: string): string { + return resolve(_dir) + } + protected getPublicDir(): string { return join(this.dir, CLIENT_PUBLIC_FILES_PATH) } + protected getDistDir(): string { + return join(this.dir, this.nextConfig.distDir) + } + + protected getPagesDir(): string { + return join( + this.distDir, + this._isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY, + 'pages' + ) + } + protected getHasStaticDir(): boolean { return fs.existsSync(join(this.dir, 'static')) } diff --git a/packages/next/server/normalize-page-path.ts b/packages/next/server/normalize-page-path.ts index f9996331e3be..943732f83eb3 100644 --- a/packages/next/server/normalize-page-path.ts +++ b/packages/next/server/normalize-page-path.ts @@ -1,6 +1,8 @@ -import { posix } from 'path' +import path from '../shared/lib/fallback/path' import { isDynamicRoute } from '../shared/lib/router/utils' +const { posix } = path + export { normalizePathSep, denormalizePagePath } from './denormalize-page-path' export function normalizePagePath(page: string): string { diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index dc1ddc3611c7..824dc200b1ee 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -1,4 +1,5 @@ import type { IncomingMessage, ServerResponse } from 'http' +import type { ParsedUrlQuery } from 'querystring' import type { NextRouter } from '../shared/lib/router/router' import type { HtmlProps } from '../shared/lib/html-context' import type { DomainLocale } from './config' @@ -20,7 +21,6 @@ import type { GetServerSideProps, GetStaticProps, PreviewData } from '../types' import type { UnwrapPromise } from '../lib/coalesced-function' import React from 'react' -import { ParsedUrlQuery, stringify as stringifyQuery } from 'querystring' import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack' import { renderToReadableStream } from 'next/dist/compiled/react-server-dom-webpack/writer.browser.server' import { StyleRegistry, createStyleRegistry } from 'styled-jsx' @@ -79,6 +79,7 @@ import { ImageConfigContext } from '../shared/lib/image-config-context' import { FlushEffectsContext } from '../shared/lib/flush-effects' import { interopDefault } from '../lib/interop-default' import stripAnsi from 'next/dist/compiled/strip-ansi' +import { urlQueryToSearchParams } from '../shared/lib/router/utils/querystring' let optimizeAmp: typeof import('./optimize-amp').default let getFontDefinitionFromManifest: typeof import('./font-utils').getFontDefinitionFromManifest @@ -518,7 +519,7 @@ export async function renderToHTML( if (isServerComponent) { serverComponentsInlinedTransformStream = new TransformStream() - const search = stringifyQuery(query) + const search = urlQueryToSearchParams(query).toString() Component = createServerComponentRenderer(AppMod, ComponentMod, { cachePrefix: pathname + (search ? `?${search}` : ''), inlinedTransformStream: serverComponentsInlinedTransformStream, diff --git a/packages/next/server/web-server.ts b/packages/next/server/web-server.ts index ef55c528109e..7f651a2fb442 100644 --- a/packages/next/server/web-server.ts +++ b/packages/next/server/web-server.ts @@ -5,8 +5,9 @@ import type { NextParsedUrlQuery } from './request-meta' import type { Params } from './router' import type { PayloadOptions } from './send-payload' import type { LoadComponentsReturnType } from './load-components' +import type { Options } from './base-server' -import BaseServer, { Options } from './base-server' +import BaseServer from './base-server' import { renderToHTML } from './render' import { byteLength, generateETag } from './api-utils/web' @@ -20,9 +21,11 @@ export default class NextWebServer extends BaseServer { constructor(options: Options & { webServerConfig: WebServerConfig }) { super(options) + this.webServerConfig = options.webServerConfig Object.assign(this.renderOpts, options.webServerConfig.extendRenderOpts) } + protected generateRewrites() { // @TODO: assuming minimal mode right now return { @@ -50,10 +53,19 @@ export default class NextWebServer extends BaseServer { // @TODO return '' } + protected getDir() { + return '.' + } protected getPublicDir() { // Public files are not handled by the web server. return '' } + protected getDistDir() { + return '' + } + protected getPagesDir() { + return '' + } protected getBuildId() { return (globalThis as any).__server_context.buildId } diff --git a/packages/next/shared/lib/fallback/path.ts b/packages/next/shared/lib/fallback/path.ts new file mode 100644 index 000000000000..b074412ddefb --- /dev/null +++ b/packages/next/shared/lib/fallback/path.ts @@ -0,0 +1,5 @@ +const path = process.browser + ? require('next/dist/compiled/path-browserify') + : require('path') + +export default path diff --git a/packages/next/shared/lib/router/utils/querystring.ts b/packages/next/shared/lib/router/utils/querystring.ts index f86d7a3c257e..3b9fa9f2068e 100644 --- a/packages/next/shared/lib/router/utils/querystring.ts +++ b/packages/next/shared/lib/router/utils/querystring.ts @@ -1,4 +1,4 @@ -import { ParsedUrlQuery } from 'querystring' +import type { ParsedUrlQuery } from 'querystring' export function searchParamsToUrlQuery( searchParams: URLSearchParams diff --git a/packages/next/types/misc.d.ts b/packages/next/types/misc.d.ts index 9d68b3d69d37..2a4807c84a80 100644 --- a/packages/next/types/misc.d.ts +++ b/packages/next/types/misc.d.ts @@ -340,6 +340,11 @@ declare module 'next/dist/compiled/process' { export = m } +declare module 'next/dist/compiled/path-browserify' { + import m from 'path' + export = m +} + declare module 'pnp-webpack-plugin' { import webpack from 'webpack4' diff --git a/test/integration/react-18/app/pages/index.js b/test/integration/react-18/app/pages/index.js index beef70aff7f4..205e6b099767 100644 --- a/test/integration/react-18/app/pages/index.js +++ b/test/integration/react-18/app/pages/index.js @@ -19,3 +19,7 @@ export default function Index() { ) } + +export const config = { + // runtime: 'edge' +} diff --git a/test/integration/react-18/test/index.test.js b/test/integration/react-18/test/index.test.js index 43e2287ac11b..e035b081fdf9 100644 --- a/test/integration/react-18/test/index.test.js +++ b/test/integration/react-18/test/index.test.js @@ -21,6 +21,7 @@ import webdriver from 'next-webdriver' const appDir = join(__dirname, '../app') const nextConfig = new File(join(appDir, 'next.config.js')) const invalidPage = new File(join(appDir, 'pages/invalid.js')) +const indexPage = new File(join(appDir, 'pages/index.js')) describe('Basics', () => { runTests('default setting with react 18', basics) @@ -67,12 +68,14 @@ function runTestsAgainstRuntime(runtime) { invalidPage.write(`export const value = 1`) } nextConfig.replace("// runtime: 'edge'", `runtime: '${runtime}'`) + indexPage.replace("// runtime: 'edge'", `runtime: '${runtime}'`) }, afterAll: (env) => { if (env === 'dev') { invalidPage.delete() } nextConfig.restore() + indexPage.restore() }, } )