Skip to content

Commit

Permalink
Revert "feat: make enableUndici: true default and remove `node-fetc…
Browse files Browse the repository at this point in the history
…h` (vercel#49061)"

This reverts commit e6acd40.
  • Loading branch information
mikedidomizio committed May 29, 2023
1 parent 7adb273 commit 8ef2905
Show file tree
Hide file tree
Showing 23 changed files with 359 additions and 115 deletions.
Expand Up @@ -2,3 +2,4 @@ import 'next/dist/server/node-polyfill-fetch'
import 'next/dist/server/node-polyfill-web-streams'
import 'next/dist/server/node-polyfill-headers'
import './async-local-storage'
;(globalThis as any).__NEXT_USE_UNDICI = true
2 changes: 1 addition & 1 deletion packages/next/src/build/index.ts
Expand Up @@ -1263,6 +1263,7 @@ export default async function build(
configFileName,
runtimeEnvConfig,
httpAgentOptions: config.httpAgentOptions,
enableUndici: config.experimental.enableUndici,
locales: config.i18n?.locales,
defaultLocale: config.i18n?.defaultLocale,
nextConfigOutput: config.output,
Expand Down Expand Up @@ -1422,7 +1423,6 @@ export default async function build(
if (pageType === 'app' || !isReservedPage(page)) {
try {
let edgeInfo: any

if (isEdgeRuntime(pageRuntime)) {
if (pageType === 'app') {
edgeRuntimeAppCount++
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/build/utils.ts
Expand Up @@ -1327,6 +1327,7 @@ export async function isPageStatic({
configFileName,
runtimeEnvConfig,
httpAgentOptions,
enableUndici,
locales,
defaultLocale,
parentId,
Expand All @@ -1344,6 +1345,7 @@ export async function isPageStatic({
configFileName: string
runtimeEnvConfig: any
httpAgentOptions: NextConfigComplete['httpAgentOptions']
enableUndici?: NextConfigComplete['experimental']['enableUndici']
locales?: string[]
defaultLocale?: string
parentId?: any
Expand Down Expand Up @@ -1376,6 +1378,7 @@ export async function isPageStatic({
require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig)
setHttpClientAndAgentOptions({
httpAgentOptions,
experimental: { enableUndici },
})

let componentsResult: LoadComponentsReturnType
Expand Down
4 changes: 1 addition & 3 deletions packages/next/src/cli/next-info.ts
Expand Up @@ -4,9 +4,7 @@ import childProcess from 'child_process'

import chalk from 'next/dist/compiled/chalk'
import arg from 'next/dist/compiled/arg/index.js'
const { fetch } = require('next/dist/compiled/undici') as {
fetch: typeof global.fetch
}
import fetch from 'next/dist/compiled/node-fetch'
import { printAndExit } from '../server/lib/utils'
import { CliCommand } from '../lib/commands'
import isError from '../lib/is-error'
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/export/index.ts
Expand Up @@ -725,6 +725,7 @@ export default async function exportApp(
parentSpanId: pageExportSpan.id,
httpAgentOptions: nextConfig.httpAgentOptions,
serverComponents: options.hasAppDir,
enableUndici: nextConfig.experimental.enableUndici,
debugOutput: options.debugOutput,
isrMemoryCacheSize: nextConfig.experimental.isrMemoryCacheSize,
fetchCache: nextConfig.experimental.appDir,
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/export/worker.ts
Expand Up @@ -80,6 +80,7 @@ interface ExportPageInput {
parentSpanId: any
httpAgentOptions: NextConfigComplete['httpAgentOptions']
serverComponents?: boolean
enableUndici: NextConfigComplete['experimental']['enableUndici']
debugOutput?: boolean
isrMemoryCacheSize?: NextConfigComplete['experimental']['isrMemoryCacheSize']
fetchCache?: boolean
Expand Down Expand Up @@ -137,6 +138,7 @@ export default async function exportPage({
disableOptimizedLoading,
httpAgentOptions,
serverComponents,
enableUndici,
debugOutput,
isrMemoryCacheSize,
fetchCache,
Expand All @@ -145,6 +147,7 @@ export default async function exportPage({
}: ExportPageInput): Promise<ExportPageResults> {
setHttpClientAndAgentOptions({
httpAgentOptions,
experimental: { enableUndici },
})
const exportPageSpan = trace('export-page-worker', parentSpanId)

Expand Down
30 changes: 9 additions & 21 deletions packages/next/src/lib/download-wasm-swc.ts
Expand Up @@ -3,12 +3,7 @@ import fs from 'fs'
import path from 'path'
import * as Log from '../build/output/log'
import tar from 'next/dist/compiled/tar'
const { fetch } = require('next/dist/compiled/undici') as {
fetch: typeof global.fetch
}
const { WritableStream } = require('node:stream/web') as {
WritableStream: typeof global.WritableStream
}
import fetch from 'next/dist/compiled/node-fetch'
import { fileExists } from './file-exists'
import { getRegistry } from './helpers/get-registry'

Expand Down Expand Up @@ -102,24 +97,17 @@ export async function downloadWasmSwc(
const registry = getRegistry()

await fetch(`${registry}${pkgName}/-/${tarFileName}`).then((res) => {
const { ok, body } = res
if (!ok) {
if (!res.ok) {
throw new Error(`request failed with status ${res.status}`)
}
if (!body) {
throw new Error('request failed with empty body')
}
const cacheWriteStream = fs.createWriteStream(tempFile)
return body.pipeTo(
new WritableStream({
write(chunk) {
cacheWriteStream.write(chunk)
},
close() {
cacheWriteStream.close()
},
})
)

return new Promise<void>((resolve, reject) => {
res.body
.pipe(cacheWriteStream)
.on('error', (err) => reject(err))
.on('finish', () => resolve())
}).finally(() => cacheWriteStream.close())
})
await fs.promises.rename(tempFile, path.join(cacheDirectory, tarFileName))
}
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/server/config-schema.ts
Expand Up @@ -420,6 +420,9 @@ const configSchema = {
},
type: 'array',
},
enableUndici: {
type: 'boolean',
},
workerThreads: {
type: 'boolean',
},
Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/server/config-shared.ts
Expand Up @@ -217,6 +217,7 @@ export interface ExperimentalConfig {
* [webpack/webpack#ModuleNotoundError.js#L13-L42](https://github.com/webpack/webpack/blob/2a0536cf510768111a3a6dceeb14cb79b9f59273/lib/ModuleNotFoundError.js#L13-L42)
*/
fallbackNodePolyfills?: false
enableUndici?: boolean
sri?: {
algorithm?: SubresourceIntegrityAlgorithm
}
Expand Down Expand Up @@ -702,6 +703,7 @@ export const defaultConfig: NextConfig = {
disablePostcssPresetEnv: undefined,
amp: undefined,
urlImports: undefined,
enableUndici: false,
adjustFontFallbacks: false,
adjustFontFallbacksWithSizeAdjust: false,
turbo: undefined,
Expand Down
37 changes: 32 additions & 5 deletions packages/next/src/server/config.ts
Expand Up @@ -19,11 +19,17 @@ import {
import { loadWebpackHook } from './config-utils'
import { ImageConfig, imageConfigDefault } from '../shared/lib/image-config'
import { loadEnvConfig, updateInitialEnv } from '@next/env'
import { gte as semverGte } from 'next/dist/compiled/semver'
import { flushAndExit } from '../telemetry/flush-and-exit'
import { findRootDir } from '../lib/find-root'

export { DomainLocale, NextConfig, normalizeConfig } from './config-shared'

const NODE_16_VERSION = '16.8.0'
const NODE_18_VERSION = '18.0.0'
const isAboveNodejs16 = semverGte(process.version, NODE_16_VERSION)
const isAboveNodejs18 = semverGte(process.version, NODE_18_VERSION)

const experimentalWarning = execOnce(
(configFileName: string, features: string[]) => {
const s = features.length > 1 ? 's' : ''
Expand All @@ -43,9 +49,26 @@ const experimentalWarning = execOnce(
}
)

export function setHttpClientAndAgentOptions(config: {
httpAgentOptions?: NextConfig['httpAgentOptions']
}) {
export function setHttpClientAndAgentOptions(
config: {
httpAgentOptions?: NextConfig['httpAgentOptions']
experimental?: {
enableUndici?: boolean
}
},
silent = false
) {
if (isAboveNodejs16) {
// Node.js 18 has undici built-in.
if (config.experimental?.enableUndici && !isAboveNodejs18) {
// When appDir is enabled undici is the default because of Response.clone() issues in node-fetch
;(globalThis as any).__NEXT_USE_UNDICI = config.experimental?.enableUndici
}
} else if (config.experimental?.enableUndici && !silent) {
Log.warn(
`\`enableUndici\` option requires Node.js v${NODE_16_VERSION} or greater. Falling back to \`node-fetch\``
)
}
if ((globalThis as any).__NEXT_HTTP_AGENT) {
// We only need to assign once because we want
// to reuse the same agent for all requests.
Expand Down Expand Up @@ -263,6 +286,10 @@ function assignDefaults(
)
}

if (result.experimental?.appDir) {
result.experimental.enableUndici = true
}

if (result.basePath !== '') {
if (result.basePath === '/') {
throw new Error(
Expand Down Expand Up @@ -485,7 +512,7 @@ function assignDefaults(
result.output = undefined
}

setHttpClientAndAgentOptions(result || defaultConfig)
setHttpClientAndAgentOptions(result || defaultConfig, silent)

if (result.i18n) {
const { i18n } = result
Expand Down Expand Up @@ -832,6 +859,6 @@ export default async function loadConfig(
silent
) as NextConfigComplete
completeConfig.configFileName = configFileName
setHttpClientAndAgentOptions(completeConfig)
setHttpClientAndAgentOptions(completeConfig, silent)
return completeConfig
}
2 changes: 2 additions & 0 deletions packages/next/src/server/dev/next-dev-server.ts
Expand Up @@ -1650,6 +1650,7 @@ export default class DevServer extends Server {
publicRuntimeConfig,
serverRuntimeConfig,
httpAgentOptions,
experimental: { enableUndici },
} = this.nextConfig
const { locales, defaultLocale } = this.nextConfig.i18n || {}
const staticPathsWorker = this.getStaticPathsWorker()
Expand All @@ -1664,6 +1665,7 @@ export default class DevServer extends Server {
serverRuntimeConfig,
},
httpAgentOptions,
enableUndici,
locales,
defaultLocale,
originalAppPath,
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/server/dev/static-paths-worker.ts
Expand Up @@ -26,6 +26,7 @@ export async function loadStaticPaths({
pathname,
config,
httpAgentOptions,
enableUndici,
locales,
defaultLocale,
isAppPath,
Expand All @@ -40,6 +41,7 @@ export async function loadStaticPaths({
pathname: string
config: RuntimeConfig
httpAgentOptions: NextConfigComplete['httpAgentOptions']
enableUndici: NextConfigComplete['enableUndici']
locales?: string[]
defaultLocale?: string
isAppPath?: boolean
Expand All @@ -58,6 +60,7 @@ export async function loadStaticPaths({
require('../../shared/lib/runtime-config').setConfig(config)
setHttpClientAndAgentOptions({
httpAgentOptions,
experimental: { enableUndici },
})

const components = await loadComponents({
Expand Down
39 changes: 26 additions & 13 deletions packages/next/src/server/node-polyfill-fetch.ts
Expand Up @@ -3,7 +3,9 @@

if (typeof fetch === 'undefined' && typeof globalThis.fetch === 'undefined') {
function getFetchImpl() {
return require('next/dist/compiled/undici')
return (global as any).__NEXT_USE_UNDICI
? require('next/dist/compiled/undici')
: require('next/dist/compiled/node-fetch')
}

function getRequestImpl() {
Expand All @@ -20,19 +22,30 @@ if (typeof fetch === 'undefined' && typeof globalThis.fetch === 'undefined') {
globalThis.fetch = (...args: any[]) => {
const fetchImpl = getFetchImpl()

// Undici does not support the `keepAlive` option,
// instead we have to pass a custom dispatcher
if (
!(global as any).__NEXT_HTTP_AGENT_OPTIONS?.keepAlive &&
!(global as any).__NEXT_UNDICI_AGENT_SET
) {
;(global as any).__NEXT_UNDICI_AGENT_SET = true
fetchImpl.setGlobalDispatcher(new fetchImpl.Agent({ pipelining: 0 }))
console.warn(
'Warning - Configuring `keepAlive: false` is deprecated. Use `{ headers: { connection: "close" } }` instead.'
)
if ((global as any).__NEXT_USE_UNDICI) {
// Undici does not support the `keepAlive` option,
// instead we have to pass a custom dispatcher
if (
!(global as any).__NEXT_HTTP_AGENT_OPTIONS?.keepAlive &&
!(global as any).__NEXT_UNDICI_AGENT_SET
) {
;(global as any).__NEXT_UNDICI_AGENT_SET = true
fetchImpl.setGlobalDispatcher(new fetchImpl.Agent({ pipelining: 0 }))
}
return fetchImpl.fetch(...args)
}
const agent = ({ protocol }: any) =>
protocol === 'http:'
? (global as any).__NEXT_HTTP_AGENT
: (global as any).__NEXT_HTTPS_AGENT

if (!args[1]) {
args[1] = { agent }
} else if (!args[1].agent) {
args[1].agent = agent
}
return fetchImpl.fetch(...args)

return fetchImpl(...args)
}

Object.defineProperties(global, {
Expand Down
9 changes: 2 additions & 7 deletions packages/next/src/telemetry/post-payload.ts
@@ -1,20 +1,15 @@
import retry from 'next/dist/compiled/async-retry'
const { fetch } = require('next/dist/compiled/undici') as {
fetch: typeof global.fetch
}
import fetch from 'next/dist/compiled/node-fetch'

export function _postPayload(endpoint: string, body: object, signal?: any) {
if (!signal && 'timeout' in AbortSignal) {
// @ts-expect-error Needs @types/node@16.14.0 or newer
signal = AbortSignal.timeout(5000)
}
return (
retry(
() =>
fetch(endpoint, {
method: 'POST',
body: JSON.stringify(body),
headers: { 'content-type': 'application/json' },
timeout: 5000,
signal,
}).then((res) => {
if (!res.ok) {
Expand Down
4 changes: 2 additions & 2 deletions packages/next/taskfile-swc.js
Expand Up @@ -70,8 +70,8 @@ module.exports = function (task) {
},
env: {
targets: {
// Follows version defined in packages/next/package.json#engine
// Currently a few minors behind due to babel class transpiling
// Should match version defined in packages/next/package.json#engine
// Should also match NODE_16_VERSION in packages/next/src/server/config.ts
node: '16.8.0',
},
},
Expand Down

0 comments on commit 8ef2905

Please sign in to comment.