rsnext/packages/next/server/dev/static-paths-worker.ts
Ethan Arrowood e0cc9cd44f
feat(experimental): option to polyfill fetch using undici in Node.js <18 (#40318)
This PR adds a new `experimental.enableUndici` option to let the
developer switch from `next-fetch` to `undici` as the underlying
polyfill for `fetch` in Node.js.

In the current implementation, Next.js makes sure that `fetch` is always
available by using `node-fetch`. However, we do not polyfill in Node.js
18+, since those versions come with their own `fetch` implementation
already, built-in.

Node.js 18+ uses `undici` under the hood, so letting the developer use
`undici` earlier could make the migration easier later on.

Eventually, we hope to be able to stop polyfilling `fetch` in an
upcoming major version of Next.js, shipping less code.


## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)

Co-authored-by: Balázs Orbán <info@balazsorban.com>
Co-authored-by: Sukka <isukkaw@gmail.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Co-authored-by: Steven <steven@ceriously.com>
2022-09-27 13:37:28 -07:00

92 lines
2.2 KiB
TypeScript

import type { NextConfigComplete } from '../config-shared'
import '../node-polyfill-fetch'
import {
buildAppStaticPaths,
buildStaticPaths,
collectGenerateParams,
} from '../../build/utils'
import { loadComponents } from '../load-components'
import { setHttpClientAndAgentOptions } from '../config'
type RuntimeConfig = any
let workerWasUsed = false
// we call getStaticPaths in a separate process to ensure
// side-effects aren't relied on in dev that will break
// during a production build
export async function loadStaticPaths({
distDir,
pathname,
serverless,
config,
httpAgentOptions,
enableUndici,
locales,
defaultLocale,
isAppPath,
originalAppPath,
}: {
distDir: string
pathname: string
serverless: boolean
config: RuntimeConfig
httpAgentOptions: NextConfigComplete['httpAgentOptions']
enableUndici: NextConfigComplete['enableUndici']
locales?: string[]
defaultLocale?: string
isAppPath?: boolean
originalAppPath?: string
}): Promise<{
paths?: string[]
encodedPaths?: string[]
fallback?: boolean | 'blocking'
}> {
// we only want to use each worker once to prevent any invalid
// caches
if (workerWasUsed) {
process.exit(1)
}
// update work memory runtime-config
require('../../shared/lib/runtime-config').setConfig(config)
setHttpClientAndAgentOptions({
httpAgentOptions,
experimental: { enableUndici },
})
const components = await loadComponents({
distDir,
pathname: originalAppPath || pathname,
serverless,
hasServerComponents: false,
isAppPath: !!isAppPath,
})
if (!components.getStaticPaths && !isAppPath) {
// we shouldn't get to this point since the worker should
// only be called for SSG pages with getStaticPaths
throw new Error(
`Invariant: failed to load page with getStaticPaths for ${pathname}`
)
}
workerWasUsed = true
if (isAppPath) {
const generateParams = collectGenerateParams(components.ComponentMod.tree)
return buildAppStaticPaths({
page: pathname,
generateParams,
configFileName: config.configFileName,
})
}
return buildStaticPaths({
page: pathname,
getStaticPaths: components.getStaticPaths,
configFileName: config.configFileName,
locales,
defaultLocale,
})
}