Skip to content

Commit

Permalink
Merge branch 'canary' into shuding/next-595-fix-client-references-exp…
Browse files Browse the repository at this point in the history
…orted-from-esm
  • Loading branch information
ijjk authored Feb 21, 2023
2 parents 3579f1d + c765fad commit b5dce65
Show file tree
Hide file tree
Showing 33 changed files with 1,422 additions and 950 deletions.
312 changes: 220 additions & 92 deletions .github/workflows/build_test_deploy.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/next/src/build/build-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const NextBuildContext: Partial<{
mappedRootPaths: {
[page: string]: string
}
hasInstrumentationHook: boolean

// misc fields
telemetryPlugin: TelemetryPlugin
Expand Down
18 changes: 18 additions & 0 deletions packages/next/src/build/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ROOT_DIR_ALIAS,
APP_DIR_ALIAS,
WEBPACK_LAYERS,
INSTRUMENTATION_HOOK_FILENAME,
} from '../lib/constants'
import { isAPIRoute } from '../lib/is-api-route'
import { isEdgeRuntime } from '../lib/is-edge-runtime'
Expand All @@ -36,6 +37,7 @@ import { warn } from './output/log'
import {
isMiddlewareFile,
isMiddlewareFilename,
isInstrumentationHookFile,
NestedMiddlewareError,
} from './utils'
import { getPageStaticInfo } from './analysis/get-page-static-info'
Expand Down Expand Up @@ -148,6 +150,7 @@ export interface CreateEntrypointsParams {
appDir?: string
appPaths?: Record<string, string>
pageExtensions: string[]
hasInstrumentationHook?: boolean
}

export function getEdgeServerEntry(opts: {
Expand All @@ -163,6 +166,7 @@ export function getEdgeServerEntry(opts: {
middleware?: Partial<MiddlewareConfig>
pagesType: 'app' | 'pages' | 'root'
appDirLoader?: string
hasInstrumentationHook?: boolean
}) {
if (
opts.pagesType === 'app' &&
Expand Down Expand Up @@ -200,6 +204,13 @@ export function getEdgeServerEntry(opts: {
return `next-edge-function-loader?${stringify(loaderParams)}!`
}

if (isInstrumentationHookFile(opts.page)) {
return {
import: opts.page,
filename: `edge-${INSTRUMENTATION_HOOK_FILENAME}.js`,
}
}

const loaderParams: EdgeSSRLoaderQuery = {
absolute500Path: opts.pages['/500'] || '',
absoluteAppPath: opts.pages['/_app'],
Expand Down Expand Up @@ -267,7 +278,13 @@ export async function runDependingOnPageType<T>(params: {
onServer: () => T
page: string
pageRuntime: ServerRuntime
pageType?: 'app' | 'pages' | 'root'
}): Promise<void> {
if (params.pageType === 'root' && isInstrumentationHookFile(params.page)) {
await Promise.all([params.onServer(), params.onEdgeServer()])
return
}

if (isMiddlewareFile(params.page)) {
await params.onEdgeServer()
return
Expand Down Expand Up @@ -404,6 +421,7 @@ export async function createEntrypoints(params: CreateEntrypointsParams) {
await runDependingOnPageType({
page,
pageRuntime: staticInfo.runtime,
pageType: pagesType,
onClient: () => {
if (isServerComponent || isInsideAppDir) {
// We skip the initial entries for server component pages and let the
Expand Down
22 changes: 21 additions & 1 deletion packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
PUBLIC_DIR_MIDDLEWARE_CONFLICT,
MIDDLEWARE_FILENAME,
PAGES_DIR_ALIAS,
INSTRUMENTATION_HOOK_FILENAME,
} from '../lib/constants'
import { fileExists } from '../lib/file-exists'
import { findPagesDir } from '../lib/find-pages-dir'
Expand Down Expand Up @@ -513,11 +514,30 @@ export default async function build(
`^${MIDDLEWARE_FILENAME}\\.(?:${config.pageExtensions.join('|')})$`
)

const instrumentationHookDetectionRegExp = new RegExp(
`^${INSTRUMENTATION_HOOK_FILENAME}\\.(?:${config.pageExtensions.join(
'|'
)})$`
)

const rootDir = path.join((pagesDir || appDir)!, '..')
const instrumentationHookEnabled = Boolean(
config.experimental.instrumentationHook
)
const rootPaths = (
await flatReaddir(rootDir, middlewareDetectionRegExp)
await flatReaddir(rootDir, [
middlewareDetectionRegExp,
...(instrumentationHookEnabled
? [instrumentationHookDetectionRegExp]
: []),
])
).map((absoluteFile) => absoluteFile.replace(dir, ''))

const hasInstrumentationHook = rootPaths.some((p) =>
p.includes(INSTRUMENTATION_HOOK_FILENAME)
)
NextBuildContext.hasInstrumentationHook = hasInstrumentationHook

// needed for static exporting since we want to replace with HTML
// files

Expand Down
24 changes: 24 additions & 0 deletions packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
SERVER_PROPS_GET_INIT_PROPS_CONFLICT,
SERVER_PROPS_SSG_CONFLICT,
MIDDLEWARE_FILENAME,
INSTRUMENTATION_HOOK_FILENAME,
} from '../lib/constants'
import { MODERN_BROWSERSLIST_TARGET } from '../shared/lib/constants'
import prettyBytes from '../lib/pretty-bytes'
Expand Down Expand Up @@ -286,6 +287,13 @@ export function isMiddlewareFilename(file?: string) {
return file === MIDDLEWARE_FILENAME || file === `src/${MIDDLEWARE_FILENAME}`
}

export function isInstrumentationHookFilename(file?: string) {
return (
file === INSTRUMENTATION_HOOK_FILENAME ||
file === `src/${INSTRUMENTATION_HOOK_FILENAME}`
)
}

export interface PageInfo {
isHybridAmp?: boolean
size: number
Expand Down Expand Up @@ -1840,6 +1848,22 @@ export function isMiddlewareFile(file: string) {
)
}

export function isInstrumentationHookFile(file: string) {
return (
file === `/${INSTRUMENTATION_HOOK_FILENAME}` ||
file === `/src/${INSTRUMENTATION_HOOK_FILENAME}`
)
}

export function getPossibleInstrumentationHookFilenames(
folder: string,
extensions: string[]
) {
return extensions.map((extension) =>
path.join(folder, `${INSTRUMENTATION_HOOK_FILENAME}.${extension}`)
)
}

export function getPossibleMiddlewareFilenames(
folder: string,
extensions: string[]
Expand Down
10 changes: 6 additions & 4 deletions packages/next/src/build/webpack-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,32 +60,34 @@ async function webpackBuildImpl(): Promise<{
const nextBuildSpan = NextBuildContext.nextBuildSpan!
const buildSpinner = NextBuildContext.buildSpinner
const dir = NextBuildContext.dir!
const config = NextBuildContext.config!

const runWebpackSpan = nextBuildSpan.traceChild('run-webpack-compiler')
const entrypoints = await nextBuildSpan
.traceChild('create-entrypoints')
.traceAsyncFn(() =>
createEntrypoints({
buildId: NextBuildContext.buildId!,
config: NextBuildContext.config!,
config: config,
envFiles: NextBuildContext.loadedEnvFiles!,
isDev: false,
rootDir: dir,
pageExtensions: NextBuildContext.config!.pageExtensions!,
pageExtensions: config.pageExtensions!,
pagesDir: NextBuildContext.pagesDir!,
appDir: NextBuildContext.appDir!,
pages: NextBuildContext.mappedPages!,
appPaths: NextBuildContext.mappedAppPages!,
previewMode: NextBuildContext.previewProps!,
rootPaths: NextBuildContext.mappedRootPaths!,
hasInstrumentationHook: NextBuildContext.hasInstrumentationHook!,
})
)

const commonWebpackOptions = {
isServer: false,
buildId: NextBuildContext.buildId!,
config: NextBuildContext.config!,
target: NextBuildContext.config!.target!,
config: config,
target: config.target!,
appDir: NextBuildContext.appDir!,
pagesDir: NextBuildContext.pagesDir!,
rewrites: NextBuildContext.rewrites!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default async function edgeSSRLoader(this: any) {
import { getRender } from 'next/dist/esm/build/webpack/loaders/next-edge-ssr-loader/render'
enhanceGlobals()
const pageType = ${JSON.stringify(pagesType)}
${
isAppDir
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NextConfig } from '../../../../server/config-shared'
import type { NextConfigComplete } from '../../../../server/config-shared'

import type { DocumentType, AppType } from '../../../../shared/lib/utils'
import type { BuildManifest } from '../../../../server/get-page-files'
Expand Down Expand Up @@ -48,7 +48,7 @@ export function getRender({
serverComponentManifest: any
serverCSSManifest: any
appServerMod: any
config: NextConfig
config: NextConfigComplete
buildId: string
fontLoaderManifest: FontLoaderManifest
}) {
Expand Down
14 changes: 12 additions & 2 deletions packages/next/src/build/webpack/plugins/middleware-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { Telemetry } from '../../../telemetry/storage'
import { traceGlobals } from '../../../trace/shared'
import { EVENT_BUILD_FEATURE_USAGE } from '../../../telemetry/events'
import { normalizeAppPath } from '../../../shared/lib/router/utils/app-paths'
import { INSTRUMENTATION_HOOK_FILENAME } from '../../../lib/constants'
import { NextBuildContext } from '../../build-context'

export interface EdgeFunctionDefinition {
env: string[]
Expand Down Expand Up @@ -90,7 +92,9 @@ function isUsingIndirectEvalAndUsedByExports(args: {
function getEntryFiles(
entryFiles: string[],
meta: EntryMetadata,
opts: { sriEnabled: boolean }
opts: {
sriEnabled: boolean
}
) {
const files: string[] = []
if (meta.edgeSSR) {
Expand Down Expand Up @@ -121,6 +125,10 @@ function getEntryFiles(
)

files.push(`server/${FONT_LOADER_MANIFEST}.js`)

if (NextBuildContext!.hasInstrumentationHook) {
files.push(`server/edge-${INSTRUMENTATION_HOOK_FILENAME}.js`)
}
}

files.push(
Expand All @@ -134,7 +142,9 @@ function getEntryFiles(
function getCreateAssets(params: {
compilation: webpack.Compilation
metadataByEntry: Map<string, EntryMetadata>
opts: { sriEnabled: boolean }
opts: {
sriEnabled: boolean
}
}) {
const { compilation, metadataByEntry, opts } = params
return (assets: any) => {
Expand Down
73 changes: 64 additions & 9 deletions packages/next/src/cli/next-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { fileExists } from '../lib/file-exists'
import Watchpack from 'next/dist/compiled/watchpack'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { warn } from '../build/output/log'
import { getPossibleInstrumentationHookFilenames } from '../build/utils'

let isTurboSession = false
let sessionStopHandled = false
Expand Down Expand Up @@ -513,8 +514,12 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit

return execArgv
}
let childProcessExitUnsub: (() => void) | null = null

const setupFork = (env?: NodeJS.ProcessEnv, newDir?: string) => {
childProcessExitUnsub?.()
childProcess?.kill()

const startDir = dir
const [, script, ...nodeArgs] = process.argv
let shouldFilter = false
Expand Down Expand Up @@ -580,10 +585,11 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit
}
}
childProcess?.addListener('exit', callback)
return () => childProcess?.removeListener('exit', callback)
childProcessExitUnsub = () =>
childProcess?.removeListener('exit', callback)
}

let childProcessExitUnsub = setupFork()
setupFork()

config = await loadConfig(
PHASE_DEVELOPMENT_SERVER,
Expand All @@ -594,10 +600,8 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit
)

const handleProjectDirRename = (newDir: string) => {
childProcessExitUnsub()
childProcess?.kill()
process.chdir(newDir)
childProcessExitUnsub = setupFork(
setupFork(
{
...Object.keys(process.env).reduce((newEnv, key) => {
newEnv[key] = process.env[key]?.replace(dir, newDir)
Expand All @@ -610,21 +614,72 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit
}
const parentDir = path.join('/', dir, '..')
const watchedEntryLength = parentDir.split('/').length + 1
const previousItems = new Set()
const previousItems = new Set<string>()

const instrumentationFilePaths = !!config.experimental
?.instrumentationHook
? getPossibleInstrumentationHookFilenames(dir, config.pageExtensions!)
: []

const wp = new Watchpack({
ignored: (entry: string) => {
// watch only one level
return !(entry.split('/').length <= watchedEntryLength)
return (
!(entry.split('/').length <= watchedEntryLength) &&
!instrumentationFilePaths.includes(entry)
)
},
})

wp.watch({ directories: [parentDir], startTime: 0 })
let instrumentationFileLastHash: string | undefined = undefined

wp.on('aggregated', () => {
wp.on('aggregated', async () => {
const knownFiles = wp.getTimeInfoEntries()
const newFiles: string[] = []
let hasPagesApp = false
// check if the `instrumentation.js` has changed
// if it has we need to restart the server
const instrumentationFile = [...knownFiles.keys()].find((key) =>
instrumentationFilePaths.includes(key)
)

if (instrumentationFile) {
const fs = require('fs') as typeof import('fs')
const instrumentationFileHash = (
require('crypto') as typeof import('crypto')
)
.createHash('sha256')
.update(await fs.promises.readFile(instrumentationFile, 'utf8'))
.digest('hex')

if (
instrumentationFileLastHash &&
instrumentationFileHash !== instrumentationFileLastHash
) {
warn(
`The instrumentation file has changed, restarting the server to apply changes.`
)
return setupFork()
} else {
if (!instrumentationFileLastHash && previousItems.size !== 0) {
warn(
'An instrumentation file was added, restarting the server to apply changes.'
)
return setupFork()
}
instrumentationFileLastHash = instrumentationFileHash
}
} else if (
[...previousItems.keys()].find((key) =>
instrumentationFilePaths.includes(key)
)
) {
warn(
`The instrumentation file has been removed, restarting the server to apply changes.`
)
instrumentationFileLastHash = undefined
return setupFork()
}

// if the dir still exists nothing to check
try {
Expand Down
Loading

0 comments on commit b5dce65

Please sign in to comment.