e0cc9cd44f
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>
56 lines
1.4 KiB
JavaScript
56 lines
1.4 KiB
JavaScript
// Polyfill fetch() in the Node.js environment
|
|
|
|
if (!global.fetch) {
|
|
function getFetchImpl() {
|
|
return global.__NEXT_USE_UNDICI
|
|
? require('next/dist/compiled/undici')
|
|
: require('next/dist/compiled/node-fetch')
|
|
}
|
|
// Due to limitation of global configuration, we have to do this resolution at runtime
|
|
global.fetch = (...args) => {
|
|
const fetchImpl = getFetchImpl()
|
|
|
|
if (global.__NEXT_USE_UNDICI) {
|
|
// Undici does not support the `keepAlive` option,
|
|
// instead we have to pass a custom dispatcher
|
|
if (
|
|
!global.__NEXT_HTTP_AGENT_OPTIONS?.keepAlive &&
|
|
!global.__NEXT_UNDICI_AGENT_SET
|
|
) {
|
|
global.__NEXT_UNDICI_AGENT_SET = true
|
|
fetchImpl.setGlobalDispatcher(new fetchImpl.Agent({ pipelining: 0 }))
|
|
}
|
|
return fetchImpl.fetch(...args)
|
|
}
|
|
const agent = ({ protocol }) =>
|
|
protocol === 'http:'
|
|
? global.__NEXT_HTTP_AGENT
|
|
: global.__NEXT_HTTPS_AGENT
|
|
|
|
if (!args[1]) {
|
|
args[1] = { agent }
|
|
} else if (!args[1].agent) {
|
|
args[1].agent = agent
|
|
}
|
|
|
|
return fetchImpl(...args)
|
|
}
|
|
|
|
Object.defineProperties(global, {
|
|
Headers: {
|
|
get() {
|
|
return getFetchImpl().Headers
|
|
},
|
|
},
|
|
Request: {
|
|
get() {
|
|
return getFetchImpl().Request
|
|
},
|
|
},
|
|
Response: {
|
|
get() {
|
|
return getFetchImpl().Response
|
|
},
|
|
},
|
|
})
|
|
}
|