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 entries.ts #48460

Merged
merged 3 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
216 changes: 118 additions & 98 deletions packages/next/src/build/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import {
isMiddlewareFile,
isMiddlewareFilename,
isInstrumentationHookFile,
NestedMiddlewareError,
} from './utils'
import { getPageStaticInfo } from './analysis/get-page-static-info'
import { normalizePathSep } from '../shared/lib/page-path/normalize-path-sep'
Expand All @@ -67,6 +66,32 @@ export function getPageFromPath(pagePath: string, pageExtensions: string[]) {
return page === '' ? '/' : page
}

function getPageFilePath({
absolutePagePath,
pagesDir,
appDir,
rootDir,
}: {
absolutePagePath: string
pagesDir: string | undefined
appDir: string | undefined
rootDir: string
}) {
if (absolutePagePath.startsWith(PAGES_DIR_ALIAS) && pagesDir) {
return absolutePagePath.replace(PAGES_DIR_ALIAS, pagesDir)
}

if (absolutePagePath.startsWith(APP_DIR_ALIAS) && appDir) {
return absolutePagePath.replace(APP_DIR_ALIAS, appDir)
}

if (absolutePagePath.startsWith(ROOT_DIR_ALIAS)) {
return absolutePagePath.replace(ROOT_DIR_ALIAS, rootDir)
}

return require.resolve(absolutePagePath)
}

export function createPagesMapping({
isDev,
pageExtensions,
Expand Down Expand Up @@ -328,7 +353,14 @@ export async function runDependingOnPageType<T>(params: {
return
}

export async function createEntrypoints(params: CreateEntrypointsParams) {
export async function createEntrypoints(
params: CreateEntrypointsParams
): Promise<{
client: webpack.EntryObject
server: webpack.EntryObject
edgeServer: webpack.EntryObject
middlewareMatchers: undefined
}> {
const {
config,
pages,
Expand All @@ -343,7 +375,6 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
const edgeServer: webpack.EntryObject = {}
const server: webpack.EntryObject = {}
const client: webpack.EntryObject = {}
const nestedMiddleware: string[] = []
let middlewareMatchers: MiddlewareMatcher[] | undefined = undefined

let appPathsPerRoute: Record<string, string[]> = {}
Expand All @@ -367,8 +398,11 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
}

const getEntryHandler =
(mappings: Record<string, string>, pagesType: 'app' | 'pages' | 'root') =>
async (page: string) => {
(
mappings: Record<string, string>,
pagesType: 'app' | 'pages' | 'root'
): ((page: string) => void) =>
async (page) => {
const bundleFile = normalizePagePath(page)
const clientBundlePath = posix.join(pagesType, bundleFile)
const serverBundlePath =
Expand All @@ -380,33 +414,12 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
const absolutePagePath = mappings[page]

// Handle paths that have aliases
const pageFilePath = (() => {
if (absolutePagePath.startsWith(PAGES_DIR_ALIAS) && pagesDir) {
return absolutePagePath.replace(PAGES_DIR_ALIAS, pagesDir)
}

if (absolutePagePath.startsWith(APP_DIR_ALIAS) && appDir) {
return absolutePagePath.replace(APP_DIR_ALIAS, appDir)
}

if (absolutePagePath.startsWith(ROOT_DIR_ALIAS)) {
return absolutePagePath.replace(ROOT_DIR_ALIAS, rootDir)
}

return require.resolve(absolutePagePath)
})()

/**
* When we find a middleware file that is not in the ROOT_DIR we fail.
* There is no need to check on `dev` as this should only happen when
* building for production.
*/
if (
!absolutePagePath.startsWith(ROOT_DIR_ALIAS) &&
/[\\\\/]_middleware$/.test(page)
) {
nestedMiddleware.push(page)
}
const pageFilePath = getPageFilePath({
absolutePagePath,
pagesDir,
appDir,
rootDir,
})

const isInsideAppDir =
!!appDir &&
Expand Down Expand Up @@ -505,24 +518,24 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
})
}

if (appDir && appPaths) {
const promises: Promise<void[]>[] = []

if (appPaths) {
const entryHandler = getEntryHandler(appPaths, 'app')
await Promise.all(Object.keys(appPaths).map(entryHandler))
promises.push(Promise.all(Object.keys(appPaths).map(entryHandler)))
}
if (rootPaths) {
await Promise.all(
Object.keys(rootPaths).map(getEntryHandler(rootPaths, 'root'))
promises.push(
Promise.all(
Object.keys(rootPaths).map(getEntryHandler(rootPaths, 'root'))
)
)
}
await Promise.all(Object.keys(pages).map(getEntryHandler(pages, 'pages')))
promises.push(
Promise.all(Object.keys(pages).map(getEntryHandler(pages, 'pages')))
)

if (nestedMiddleware.length > 0) {
throw new NestedMiddlewareError(
nestedMiddleware,
rootDir,
(appDir || pagesDir)!
)
}
await Promise.all(promises)

return {
client,
Expand Down Expand Up @@ -551,69 +564,76 @@ export function finalizeEntrypoint({
: value

const isApi = name.startsWith('pages/api/')
if (compilerType === COMPILER_NAMES.server) {
return {
publicPath: isApi ? '' : undefined,
runtime: isApi ? 'webpack-api-runtime' : 'webpack-runtime',
layer: isApi
? WEBPACK_LAYERS.api
: isServerComponent
? WEBPACK_LAYERS.server
: undefined,
...entry,
}
}

if (compilerType === COMPILER_NAMES.edgeServer) {
return {
layer:
isMiddlewareFilename(name) || isApi
? WEBPACK_LAYERS.middleware
switch (compilerType) {
case COMPILER_NAMES.server: {
return {
publicPath: isApi ? '' : undefined,
runtime: isApi ? 'webpack-api-runtime' : 'webpack-runtime',
layer: isApi
? WEBPACK_LAYERS.api
: isServerComponent
? WEBPACK_LAYERS.server
: undefined,
library: { name: ['_ENTRIES', `middleware_[name]`], type: 'assign' },
runtime: EDGE_RUNTIME_WEBPACK,
asyncChunks: false,
...entry,
...entry,
}
}
}

const isAppLayer =
hasAppDir &&
(name === CLIENT_STATIC_FILES_RUNTIME_MAIN_APP ||
name === APP_CLIENT_INTERNALS ||
name.startsWith('app/'))

if (
// Client special cases
name !== CLIENT_STATIC_FILES_RUNTIME_POLYFILLS &&
name !== CLIENT_STATIC_FILES_RUNTIME_MAIN &&
name !== CLIENT_STATIC_FILES_RUNTIME_MAIN_APP &&
name !== CLIENT_STATIC_FILES_RUNTIME_AMP &&
name !== CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH
) {
if (isAppLayer) {
case COMPILER_NAMES.edgeServer: {
return {
dependOn: CLIENT_STATIC_FILES_RUNTIME_MAIN_APP,
layer: WEBPACK_LAYERS.appClient,
layer:
isMiddlewareFilename(name) || isApi
? WEBPACK_LAYERS.middleware
: undefined,
library: { name: ['_ENTRIES', `middleware_[name]`], type: 'assign' },
runtime: EDGE_RUNTIME_WEBPACK,
asyncChunks: false,
...entry,
}
}
case COMPILER_NAMES.client: {
const isAppLayer =
hasAppDir &&
(name === CLIENT_STATIC_FILES_RUNTIME_MAIN_APP ||
name === APP_CLIENT_INTERNALS ||
name.startsWith('app/'))

return {
dependOn:
name.startsWith('pages/') && name !== 'pages/_app'
? 'pages/_app'
: CLIENT_STATIC_FILES_RUNTIME_MAIN,
...entry,
}
}
if (
// Client special cases
name !== CLIENT_STATIC_FILES_RUNTIME_POLYFILLS &&
name !== CLIENT_STATIC_FILES_RUNTIME_MAIN &&
name !== CLIENT_STATIC_FILES_RUNTIME_MAIN_APP &&
name !== CLIENT_STATIC_FILES_RUNTIME_AMP &&
name !== CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH
) {
if (isAppLayer) {
return {
dependOn: CLIENT_STATIC_FILES_RUNTIME_MAIN_APP,
layer: WEBPACK_LAYERS.appClient,
...entry,
}
}

if (isAppLayer) {
return {
layer: WEBPACK_LAYERS.appClient,
...entry,
return {
dependOn:
name.startsWith('pages/') && name !== 'pages/_app'
? 'pages/_app'
: CLIENT_STATIC_FILES_RUNTIME_MAIN,
...entry,
}
}

if (isAppLayer) {
return {
layer: WEBPACK_LAYERS.appClient,
...entry,
}
}

return entry
}
default: {
// Should never happen.
throw new Error('Invalid compiler type')
}
}

return entry
}
44 changes: 17 additions & 27 deletions packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,31 +398,6 @@ export default async function build(
)
: []

let appPaths: string[] | undefined

if (appDir) {
appPaths = await nextBuildSpan
.traceChild('collect-app-paths')
.traceAsyncFn(() =>
recursiveReadDir(
appDir,
(absolutePath) => {
if (validFileMatcher.isAppRouterPage(absolutePath)) {
return true
}
// For now we only collect the root /not-found page in the app
// directory as the 404 fallback.
if (validFileMatcher.isRootNotFound(absolutePath)) {
return true
}
return false
},
undefined,
(part) => part.startsWith('_')
)
)
}

const middlewareDetectionRegExp = new RegExp(
`^${MIDDLEWARE_FILENAME}\\.(?:${config.pageExtensions.join('|')})$`
)
Expand Down Expand Up @@ -474,12 +449,27 @@ export default async function build(
let mappedAppPages: { [page: string]: string } | undefined
let denormalizedAppPages: string[] | undefined

if (appPaths && appDir) {
if (appDir) {
const appPaths = await nextBuildSpan
.traceChild('collect-app-paths')
.traceAsyncFn(() =>
recursiveReadDir(
appDir,
(absolutePath) =>
validFileMatcher.isAppRouterPage(absolutePath) ||
// For now we only collect the root /not-found page in the app
// directory as the 404 fallback
validFileMatcher.isRootNotFound(absolutePath),
undefined,
(part) => part.startsWith('_')
)
)

mappedAppPages = nextBuildSpan
.traceChild('create-app-mapping')
.traceFn(() =>
createPagesMapping({
pagePaths: appPaths!,
pagePaths: appPaths,
isDev: false,
pagesType: 'app',
pageExtensions: config.pageExtensions,
Expand Down
5 changes: 0 additions & 5 deletions test/integration/middleware-nested-error/middleware.js

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 0 additions & 3 deletions test/integration/middleware-nested-error/pages/index.js

This file was deleted.