Skip to content

Commit 0de109b

Browse files
authored
Refactor Page Paths utils and Middleware Plugin (#36576)
This PR brings some significant refactoring in preparation for upcoming middleware changes. Each commit can be reviewed independently, here is a summary of what each one does and the reasoning behind it: - [Move pagesDir to next-dev-server](javivelasco@f2fe154) simply moves the `pagesDir` property to the dev server which is the only place where it is needed. Having it for every server is misleading. - [Move (de)normalize page path utils to a file page-path-utils.ts](javivelasco@27cedf0) Moves the functions to normalize and denormalize page paths to a single file that is intended to hold every utility function that transforms page paths. Since those are complementary it makes sense to have them together. I also added explanatory comments on why they are not idempotent and examples for input -> output that I find very useful. - [Extract removePagePathTail](javivelasco@6b12133) This extracts a function to remove the tail on a page path (absolute or relative). I'm sure there will be other contexts where we can use it. - [Extract getPagePaths and refactor findPageFile](javivelasco@cf2c7b8) This extracts a function `getPagePaths` that is used to generate an array of paths to inspect when looking for a page file from `findPageFile`. Then it refactors such function to use it parallelizing lookups. This will allow us to print every path we look at when looking for a file which can be useful for debugging. It also adds a `flatten` helper. - [Refactor onDemandEntryHandler](javivelasco@4be685c) I've found this one quite difficult to understand so it is refactored to use some of the previously mentioned functions and make it easier to read. - [Extract absolutePagePath util](javivelasco@3bc0783) Extracts yet another util from the `next-dev-server` that transforms an absolute path into a page name. Of course it adds comments, parameters and examples. - [Refactor MiddlewarePlugin](javivelasco@c595a2c) This is the most significant change. The logic here was very hard to understand so it is totally redistributed with comments. This also removes a global variable `ssrEntries` that was deprecated in favour of module metadata added to Webpack from loaders keeping less dependencies. It also adds types and makes a clear distinction between phases where we statically analyze the code, find metadata and generate the manifest file cc @shuding @huozhi EDIT: - [Split page path utils](158fb00) After seeing one of the utils was being used by the client while it was defined originally in the server, with this PR we are splitting the util into multiple files and moving it to `shared/lib` in order to make explicit that those can be also imported from client.
1 parent 7998b63 commit 0de109b

40 files changed

+759
-590
lines changed

packages/next/build/entries.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ import { EDGE_RUNTIME_WEBPACK } from '../shared/lib/constants'
1515
import { MIDDLEWARE_ROUTE } from '../lib/constants'
1616
import { __ApiPreviewProps } from '../server/api-utils'
1717
import { isTargetLikeServerless } from '../server/utils'
18-
import { normalizePagePath } from '../server/normalize-page-path'
19-
import { normalizePathSep } from '../server/denormalize-page-path'
20-
import { ssrEntries } from './webpack/plugins/middleware-plugin'
2118
import { warn } from './output/log'
2219
import { parse } from '../build/swc'
2320
import { isFlightPage, withoutRSCExtensions } from './utils'
21+
import { normalizePathSep } from '../shared/lib/page-path/normalize-path-sep'
22+
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
2423

2524
type ObjectValue<T> = T extends { [key: string]: infer V } ? V : never
2625

@@ -233,7 +232,6 @@ export function getEdgeServerEntry(opts: {
233232
isDev: boolean
234233
page: string
235234
pages: { [page: string]: string }
236-
ssrEntries: Map<string, { requireFlightManifest: boolean }>
237235
}): ObjectValue<webpack5.EntryObject> {
238236
if (opts.page.match(MIDDLEWARE_ROUTE)) {
239237
const loaderParams: MiddlewareLoaderOptions = {
@@ -258,10 +256,6 @@ export function getEdgeServerEntry(opts: {
258256
stringifiedConfig: JSON.stringify(opts.config),
259257
}
260258

261-
ssrEntries.set(opts.bundlePath, {
262-
requireFlightManifest: isFlightPage(opts.config, opts.absolutePagePath),
263-
})
264-
265259
return `next-middleware-ssr-loader?${stringify(loaderParams)}!`
266260
}
267261

@@ -375,7 +369,6 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
375369
bundlePath: clientBundlePath,
376370
isDev: false,
377371
page,
378-
ssrEntries,
379372
})
380373
},
381374
})

packages/next/build/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import { __ApiPreviewProps } from '../server/api-utils'
6363
import loadConfig from '../server/config'
6464
import { isTargetLikeServerless } from '../server/utils'
6565
import { BuildManifest } from '../server/get-page-files'
66-
import { normalizePagePath } from '../server/normalize-page-path'
66+
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
6767
import { getPagePath } from '../server/require'
6868
import * as ciEnvironment from '../telemetry/ci-info'
6969
import {

packages/next/build/utils.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
2626
import escapePathDelimiters from '../shared/lib/router/utils/escape-path-delimiters'
2727
import { findPageFile } from '../server/lib/find-page-file'
2828
import { GetStaticPaths, PageConfig } from 'next/types'
29-
import {
30-
denormalizePagePath,
31-
normalizePagePath,
32-
} from '../server/normalize-page-path'
3329
import { BuildManifest } from '../server/get-page-files'
3430
import { removePathTrailingSlash } from '../client/normalize-trailing-slash'
3531
import { UnwrapPromise } from '../lib/coalesced-function'
@@ -42,6 +38,8 @@ import isError from '../lib/is-error'
4238
import { recursiveDelete } from '../lib/recursive-delete'
4339
import { Sema } from 'next/dist/compiled/async-sema'
4440
import { MiddlewareManifest } from './webpack/plugins/middleware-plugin'
41+
import { denormalizePagePath } from '../shared/lib/page-path/denormalize-page-path'
42+
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
4543

4644
const { builtinModules } = require('module')
4745
const RESERVED_PAGE = /^\/(_app|_error|_document|api(\/|$))/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { webpack5 } from 'next/dist/compiled/webpack/webpack'
2+
3+
/**
4+
* A getter for module build info that casts to the type it should have.
5+
* We also expose here types to make easier to use it.
6+
*/
7+
export function getModuleBuildInfo(webpackModule: webpack5.Module) {
8+
return webpackModule.buildInfo as {
9+
nextEdgeMiddleware?: EdgeMiddlewareMeta
10+
nextEdgeSSR?: EdgeSSRMeta
11+
nextUsedEnvVars?: Set<string>
12+
nextWasmMiddlewareBinding?: WasmBinding
13+
usingIndirectEval?: boolean | Set<string>
14+
}
15+
}
16+
17+
export interface EdgeMiddlewareMeta {
18+
page: string
19+
}
20+
21+
export interface EdgeSSRMeta {
22+
isServerComponent: boolean
23+
page: string
24+
}
25+
26+
export interface WasmBinding {
27+
filePath: string
28+
name: string
29+
}

packages/next/build/webpack/loaders/next-middleware-loader.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getModuleBuildInfo } from './get-module-build-info'
12
import { stringifyRequest } from '../stringify-request'
23

34
export type MiddlewareLoaderOptions = {
@@ -8,6 +9,10 @@ export type MiddlewareLoaderOptions = {
89
export default function middlewareLoader(this: any) {
910
const { absolutePagePath, page }: MiddlewareLoaderOptions = this.getOptions()
1011
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
12+
const buildInfo = getModuleBuildInfo(this._module)
13+
buildInfo.nextEdgeMiddleware = {
14+
page: page.replace(/\/_middleware$/, '') || '/',
15+
}
1116

1217
return `
1318
import { adapter } from 'next/dist/server/web/adapter'

packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getModuleBuildInfo } from '../get-module-build-info'
12
import { stringifyRequest } from '../../stringify-request'
23

34
export type MiddlewareSSRLoaderQuery = {
@@ -27,7 +28,13 @@ export default async function middlewareSSRLoader(this: any) {
2728
absoluteErrorPath,
2829
isServerComponent,
2930
stringifiedConfig,
30-
}: MiddlewareSSRLoaderQuery = this.getOptions()
31+
} = this.getOptions()
32+
33+
const buildInfo = getModuleBuildInfo(this._module)
34+
buildInfo.nextEdgeSSR = {
35+
isServerComponent: isServerComponent === 'true',
36+
page: page,
37+
}
3138

3239
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
3340
const stringifiedAppPath = stringifyRequest(this, absoluteAppPath)

packages/next/build/webpack/loaders/next-middleware-wasm-loader.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1+
import { getModuleBuildInfo } from './get-module-build-info'
12
import crypto from 'crypto'
23

3-
export type WasmBinding = {
4-
filePath: string
5-
name: string
6-
}
7-
84
export default function MiddlewareWasmLoader(this: any, source: Buffer) {
95
const name = `wasm_${sha1(source)}`
106
const filePath = `edge-chunks/${name}.wasm`
11-
const binding: WasmBinding = { filePath: `server/${filePath}`, name }
12-
this._module.buildInfo.nextWasmMiddlewareBinding = binding
7+
const buildInfo = getModuleBuildInfo(this._module)
8+
buildInfo.nextWasmMiddlewareBinding = { filePath: `server/${filePath}`, name }
139
this.emitFile(`/${filePath}`, source, null)
1410
return `module.exports = ${name};`
1511
}

packages/next/build/webpack/loaders/next-serverless-loader/page-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { getUtils, vercelHeader, ServerlessHandlerCtx } from './utils'
66

77
import { renderToHTML } from '../../../../server/render'
88
import { tryGetPreviewData } from '../../../../server/api-utils/node'
9-
import { denormalizePagePath } from '../../../../server/denormalize-page-path'
9+
import { denormalizePagePath } from '../../../../shared/lib/page-path/denormalize-page-path'
1010
import { setLazyProp, getCookieParser } from '../../../../server/api-utils'
1111
import { getRedirectStatus } from '../../../../lib/load-custom-routes'
1212
import getRouteNoAssetPath from '../../../../shared/lib/router/utils/get-route-from-asset-path'

packages/next/build/webpack/loaders/next-serverless-loader/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { __ApiPreviewProps } from '../../../../server/api-utils'
2323
import { acceptLanguage } from '../../../../server/accept-header'
2424
import { detectLocaleCookie } from '../../../../shared/lib/i18n/detect-locale-cookie'
2525
import { detectDomainLocale } from '../../../../shared/lib/i18n/detect-domain-locale'
26-
import { denormalizePagePath } from '../../../../server/denormalize-page-path'
26+
import { denormalizePagePath } from '../../../../shared/lib/page-path/denormalize-page-path'
2727
import cookie from 'next/dist/compiled/cookie'
2828
import { TEMPORARY_REDIRECT_STATUS } from '../../../../shared/lib/constants'
2929
import { addRequestMeta } from '../../../../server/request-meta'

0 commit comments

Comments
 (0)