Repository: vercel/next.js
Pull request: Handle edge runtime in places that import node:stream

## What?

The codepath would cause checks to fail during deployment because it tries to import `node:stream` even when not used. This adds a specific path for edge runtime to avoid that.

Changed files:
filename: packages/next/errors.json
patch: @@ -1145,5 +1145,8 @@
   "1144": "Prefetch inlining is enabled but no hints were found for route \"%s\". This is a bug in the Next.js build pipeline — prefetch-hints.json should contain an entry for every route that produces segment data.",
   "1145": "Internal Next.js Error: Prefetch inlining is enabled but no hints were found for route \"%s\". prefetch-hints.json should contain an entry for every route that produces segment data. This is a bug in Next.js.",
   "1146": "Internal Next.js Error: Prefetch inlining is enabled but no hint tree was provided during incremental static revalidation. The prefetch-hints.json manifest should contain an entry for this route. This is a bug in Next.js.",
-  "1147": "Turbopack database compaction is not supported on this platform"
+  "1147": "Turbopack database compaction is not supported on this platform",
+  "1148": "webToReadable cannot be used in the edge runtime",
+  "1149": "Node.js Readable cannot be teed in the edge runtime",
+  "1150": "Node.js Readable cannot be converted to a web stream in the edge runtime"
 }

filename: packages/next/src/server/app-render/app-render-prerender-utils.ts
patch: @@ -30,21 +30,29 @@ export class ReactServerResult {
       return tee[1]
     }
 
-    let Readable: typeof import('node:stream').Readable
-    if (process.env.TURBOPACK) {
-      Readable = (require('node:stream') as typeof import('node:stream'))
-        .Readable
+    if (process.env.NEXT_RUNTIME === 'edge') {
+      throw new InvariantError(
+        'Node.js Readable cannot be teed in the edge runtime'
+      )
     } else {
-      Readable = (
-        __non_webpack_require__('node:stream') as typeof import('node:stream')
-      ).Readable
+      let Readable: typeof import('node:stream').Readable
+      if (process.env.TURBOPACK) {
+        Readable = (require('node:stream') as typeof import('node:stream'))
+          .Readable
+      } else {
+        Readable = (
+          __non_webpack_require__('node:stream') as typeof import('node:stream')
+        ).Readable
+      }
+      const webStream = Readable.toWeb(
+        this._stream
+      ) as ReadableStream<Uint8Array>
+      const tee = webStream.tee()
+      this._stream = Readable.fromWeb(
+        tee[0] as import('stream/web').ReadableStream
+      )
+      return Readable.fromWeb(tee[1] as import('stream/web').ReadableStream)
     }
-    const webStream = Readable.toWeb(this._stream) as ReadableStream<Uint8Array>
-    const tee = webStream.tee()
-    this._stream = Readable.fromWeb(
-      tee[0] as import('stream/web').ReadableStream
-    )
-    return Readable.fromWeb(tee[1] as import('stream/web').ReadableStream)
   }
 
   consume(): AnyStream {

filename: packages/next/src/server/render-result.ts
patch: @@ -248,16 +248,24 @@ export default class RenderResult<
     }
 
     if (isNodeReadable(this.response)) {
-      let Readable: typeof import('node:stream').Readable
-      if (process.env.TURBOPACK) {
-        Readable = (require('node:stream') as typeof import('node:stream'))
-          .Readable
+      if (process.env.NEXT_RUNTIME === 'edge') {
+        throw new InvariantError(
+          'Node.js Readable cannot be converted to a web stream in the edge runtime'
+        )
       } else {
-        Readable = (
-          __non_webpack_require__('node:stream') as typeof import('node:stream')
-        ).Readable
+        let Readable: typeof import('node:stream').Readable
+        if (process.env.TURBOPACK) {
+          Readable = (require('node:stream') as typeof import('node:stream'))
+            .Readable
+        } else {
+          Readable = (
+            __non_webpack_require__(
+              'node:stream'
+            ) as typeof import('node:stream')
+          ).Readable
+        }
+        return Readable.toWeb(this.response) as ReadableStream<Uint8Array>
       }
-      return Readable.toWeb(this.response) as ReadableStream<Uint8Array>
     }
 
     return this.response
@@ -283,16 +291,24 @@ export default class RenderResult<
     } else if (Buffer.isBuffer(this.response)) {
       return [streamFromBuffer(this.response)]
     } else if (isNodeReadable(this.response)) {
-      let Readable: typeof import('node:stream').Readable
-      if (process.env.TURBOPACK) {
-        Readable = (require('node:stream') as typeof import('node:stream'))
-          .Readable
+      if (process.env.NEXT_RUNTIME === 'edge') {
+        throw new InvariantError(
+          'Node.js Readable cannot be converted to a web stream in the edge runtime'
+        )
       } else {
-        Readable = (
-          __non_webpack_require__('node:stream') as typeof import('node:stream')
-        ).Readable
+        let Readable: typeof import('node:stream').Readable
+        if (process.env.TURBOPACK) {
+          Readable = (require('node:stream') as typeof import('node:stream'))
+            .Readable
+        } else {
+          Readable = (
+            __non_webpack_require__(
+              'node:stream'
+            ) as typeof import('node:stream')
+          ).Readable
+        }
+        return [Readable.toWeb(this.response) as ReadableStream<Uint8Array>]
       }
-      return [Readable.toWeb(this.response) as ReadableStream<Uint8Array>]
     } else {
       return [this.response]
     }

filename: packages/next/src/server/stream-utils/node-web-streams-helper.ts
patch: @@ -135,20 +135,26 @@ export async function webstreamToUint8Array(
 function webToReadable(
   stream: ReadableStream<Uint8Array> | import('node:stream').Readable
 ): import('node:stream').Readable {
-  let Readable: typeof import('node:stream').Readable
-  if (process.env.TURBOPACK) {
-    Readable = (require('node:stream') as typeof import('node:stream')).Readable
-  } else if (process.env.__NEXT_BUNDLER === 'Webpack') {
-    Readable = (
-      __non_webpack_require__('node:stream') as typeof import('node:stream')
-    ).Readable
+  if (process.env.NEXT_RUNTIME === 'edge') {
+    throw new Error('webToReadable cannot be used in the edge runtime')
   } else {
-    Readable = (require('node:stream') as typeof import('node:stream')).Readable
-  }
-  if (stream instanceof Readable) {
-    return stream
+    let Readable: typeof import('node:stream').Readable
+    if (process.env.TURBOPACK) {
+      Readable = (require('node:stream') as typeof import('node:stream'))
+        .Readable
+    } else if (process.env.__NEXT_BUNDLER === 'Webpack') {
+      Readable = (
+        __non_webpack_require__('node:stream') as typeof import('node:stream')
+      ).Readable
+    } else {
+      Readable = (require('node:stream') as typeof import('node:stream'))
+        .Readable
+    }
+    if (stream instanceof Readable) {
+      return stream
+    }
+    return Readable.fromWeb(stream as import('stream/web').ReadableStream)
   }
-  return Readable.fromWeb(stream as import('stream/web').ReadableStream)
 }
 
 export async function nodestreamToUint8Array(
@@ -162,20 +168,29 @@ export async function nodestreamToUint8Array(
 }
 
 export async function streamToUint8Array(stream: AnyStream) {
-  let Readable: typeof import('node:stream').Readable
-  if (process.env.TURBOPACK) {
-    Readable = (require('node:stream') as typeof import('node:stream')).Readable
-  } else if (process.env.__NEXT_BUNDLER === 'Webpack') {
-    Readable = (
-      __non_webpack_require__('node:stream') as typeof import('node:stream')
-    ).Readable
+  if (process.env.NEXT_RUNTIME === 'edge') {
+    // Edge runtime always uses web streams
+    return webstreamToUint8Array(stream as ReadableStream<Uint8Array>)
   } else {
-    Readable = (require('node:stream') as typeof import('node:stream')).Readable
-  }
-  if (stream instanceof Readable) {
-    return nodestreamToUint8Array(stream)
+    let Readable: typeof import('node:stream').Readable
+    if (process.env.TURBOPACK) {
+      Readable = (require('node:stream') as typeof import('node:stream'))
+        .Readable
+    } else if (process.env.__NEXT_BUNDLER === 'Webpack') {
+      Readable = (
+        __non_webpack_require__('node:stream') as typeof import('node:stream')
+      ).Readable
+    } else {
+      Readable = (require('node:stream') as typeof import('node:stream'))
+        .Readable
+    }
+
+    if (stream instanceof Readable) {
+      return nodestreamToUint8Array(stream)
+    }
+
+    return webstreamToUint8Array(stream)
   }
-  return webstreamToUint8Array(stream)
 }
 
 export async function streamToBuffer(