mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
6ba71046b0
Node.js ships with a built-in `fetch` now so `node-fetch` is no longer necessary. Mostly motivated by tracing Node.js deprecation warnings which originated from `node-fetch` by calling the deprecated `url.parse`. Call sites keep working through a compatibility type on `fetchViaHTTP` that translates node-fetch-only options: Instead of `agent` we pass to `http(s)` directly, `timeout` becomes `AbortSignal.timeout`, and Node.js readable streams are accepted as bodies with `duplex: 'half'` set automatically. The `abort-controller` polyfill is dropped since its signal type predates the current AbortSignal and undici would not honor it. `node-fetch` stays installed because `scripts/generate-release-log.mjs`, `scripts/reset-project.mjs`, and `scripts/update-google-fonts.js` still import it (follow-up material). Fixture apps will be migrated separately.
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
/**
|
|
* Measures and separates static and dynamic content in a response stream
|
|
* by splitting on PPR boundary sentinel markers.
|
|
*
|
|
* This function is used in Partial Prerendering (PPR) tests to analyze the output
|
|
* of Next.js pages and verify that static and dynamic content are properly separated.
|
|
*
|
|
* @param fn - A function that returns a Promise resolving to a readable stream
|
|
* containing HTML with PPR boundary markers
|
|
* @returns An object containing the separated static and dynamic chunks
|
|
*
|
|
* @example
|
|
* const [staticPart, dynamicPart] = await splitResponseWithPPRSentinel(async () => {
|
|
* return fetch('/some-ppr-page').then(res => res.body)
|
|
* })
|
|
* console.log(staticPart) // Content before the boundary
|
|
* console.log(dynamicPart) // Content after the boundary
|
|
*/
|
|
export async function splitResponseWithPPRSentinel(
|
|
fn: () => Promise<ReadableStream<Uint8Array> | null>
|
|
): Promise<[staticPart: string, dynamicPart: string]> {
|
|
const stream = await fn()
|
|
if (stream === null) {
|
|
throw new Error('Expected a response body')
|
|
}
|
|
const chunks: string[] = []
|
|
|
|
const decoder = new TextDecoder()
|
|
for await (const chunk of stream) {
|
|
chunks.push(
|
|
typeof chunk === 'string'
|
|
? chunk
|
|
: decoder.decode(chunk, { stream: true })
|
|
)
|
|
}
|
|
chunks.push(decoder.decode())
|
|
|
|
// Combine all chunks and split on the PPR boundary sentinel
|
|
// The sentinel marks the boundary between static and dynamic content
|
|
const parts = chunks.join('').split('<!-- PPR_BOUNDARY_SENTINEL -->', 2)
|
|
return [parts[0] ?? '', parts[1] ?? '']
|
|
}
|