first commit
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled

This commit is contained in:
Arian Tron
2026-03-10 19:37:31 +03:30
commit 61f56f997c
27684 changed files with 2784175 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
export function GET() {
return Response.json({ name: 'John Doe' })
}
export const dynamic = 'force-dynamic'

View File

@@ -0,0 +1,12 @@
import React from 'react'
export default function Layout({ children }) {
return (
<html>
<head>
<title>My App</title>
</head>
<body>{children}</body>
</html>
)
}

View File

@@ -0,0 +1,7 @@
import React from 'react'
export default function Page() {
return <h1>My Page</h1>
}
export const dynamic = 'force-dynamic'

View File

@@ -0,0 +1,20 @@
'use client'
import React from 'react'
export function StreamingClientBoundary({
chunkId,
payload,
fragments,
checksum,
}) {
return (
<section data-client-boundary={chunkId}>
<h3>client-{chunkId}</h3>
<p>checksum:{checksum}</p>
<p>payload-bytes:{payload.length}</p>
<p>fragment-count:{fragments.length}</p>
<p>{fragments[0] ?? ''}</p>
</section>
)
}

View File

@@ -0,0 +1,105 @@
import React, { Suspense } from 'react'
import { StreamingClientBoundary } from './client-boundary'
function sleep(ms) {
if (ms <= 0) return Promise.resolve()
return new Promise((resolve) => setTimeout(resolve, ms))
}
function createPayload(title, payloadBytes) {
const prefix = `${title}:`
if (prefix.length >= payloadBytes) return prefix
return `${prefix}${'x'.repeat(payloadBytes - prefix.length)}`
}
function createClientPayload({ title, id, payloadBytes, fragmentCount }) {
const payload = createPayload(`${title}-client-${id}`, payloadBytes)
const safeFragmentCount = Math.max(1, fragmentCount)
const fragmentSize = Math.max(
16,
Math.floor(payload.length / safeFragmentCount)
)
const fragments = Array.from({ length: safeFragmentCount }, (_, index) => {
const start = Math.min(index * fragmentSize, payload.length)
const end = Math.min(start + fragmentSize, payload.length)
return payload.slice(start, end)
})
return {
chunkId: id,
payload,
fragments,
checksum: payload.length + id * 31 + safeFragmentCount,
}
}
async function StreamedChunk({
title,
id,
delayMs,
payload,
clientPayloadBytes,
clientPayloadFragments,
}) {
await sleep(delayMs)
const clientPayload = createClientPayload({
title,
id,
payloadBytes: clientPayloadBytes,
fragmentCount: clientPayloadFragments,
})
return (
<article data-chunk-id={id}>
<h2>chunk-{id}</h2>
<p>{payload}</p>
<StreamingClientBoundary {...clientPayload} />
</article>
)
}
export function StreamingStressPage({
title,
boundaryCount,
payloadBytes,
clientPayloadBytes = Math.max(128, Math.floor(payloadBytes / 2)),
clientPayloadFragments = 4,
maxDelayMs,
}) {
const payload = createPayload(title, payloadBytes)
const boundaries = Array.from({ length: boundaryCount }, (_, index) => index)
return (
<main>
<h1>{title}</h1>
<p>
boundaries={boundaryCount} payloadBytes={payloadBytes}{' '}
clientPayloadBytes=
{clientPayloadBytes} clientPayloadFragments={clientPayloadFragments}{' '}
maxDelayMs={maxDelayMs}
</p>
{boundaries.map((id) => {
const delayMs = maxDelayMs === 0 ? 0 : id % (maxDelayMs + 1)
return (
<Suspense
key={id}
fallback={<div data-fallback-id={id}>loading-{id}</div>}
>
<StreamedChunk
title={title}
id={id}
delayMs={delayMs}
payload={payload}
clientPayloadBytes={clientPayloadBytes}
clientPayloadFragments={clientPayloadFragments}
/>
</Suspense>
)
})}
</main>
)
}

View File

@@ -0,0 +1,21 @@
import React from 'react'
export const dynamic = 'force-dynamic'
const ROWS = 2500
const PAYLOAD = 'x'.repeat(384)
const DATA = Array.from(
{ length: ROWS },
(_, index) => `row-${index}-${PAYLOAD}`
)
export default function Page() {
return (
<main>
<h1>stream-bulk</h1>
{DATA.map((line, index) => (
<p key={index}>{line}</p>
))}
</main>
)
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StreamingStressPage } from '../_shared/stress-page'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<StreamingStressPage
title="stream-chunkstorm"
boundaryCount={960}
payloadBytes={192}
clientPayloadBytes={1024}
clientPayloadFragments={4}
maxDelayMs={3}
/>
)
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StreamingStressPage } from '../_shared/stress-page'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<StreamingStressPage
title="stream-heavy"
boundaryCount={240}
payloadBytes={1536}
clientPayloadBytes={3072}
clientPayloadFragments={6}
maxDelayMs={8}
/>
)
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StreamingStressPage } from '../_shared/stress-page'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<StreamingStressPage
title="stream-light"
boundaryCount={24}
payloadBytes={512}
clientPayloadBytes={384}
clientPayloadFragments={2}
maxDelayMs={2}
/>
)
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StreamingStressPage } from '../_shared/stress-page'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<StreamingStressPage
title="stream-medium"
boundaryCount={96}
payloadBytes={1024}
clientPayloadBytes={1024}
clientPayloadFragments={4}
maxDelayMs={4}
/>
)
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StreamingStressPage } from '../_shared/stress-page'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<StreamingStressPage
title="stream-wide"
boundaryCount={120}
payloadBytes={8192}
clientPayloadBytes={16384}
clientPayloadFragments={8}
maxDelayMs={6}
/>
)
}

View File

@@ -0,0 +1,142 @@
#!/bin/bash
# Benchmark script for comparing web streams vs node streams performance.
# Uses the minimal server (bench/next-minimal-server) for lowest overhead.
# Warms up with 50 requests, then runs two phases:
# Phase 1: 10s at concurrency=1 (single-client latency)
# Phase 2: 10s at concurrency=100 (throughput under load)
# Reports throughput and latency percentiles for each phase.
#
# Usage:
# ./benchmark.sh [duration] [warmup_requests]
#
# Defaults: 10s duration per phase, 50 warmup requests
set -euo pipefail
DURATION=${1:-10}
WARMUP_REQS=${2:-50}
PORT=3199
NEXT_BIN="../../packages/next/dist/bin/next"
MINIMAL_SERVER="../next-minimal-server/bin/minimal-server.js"
if ! command -v npx &>/dev/null; then
echo "npx is required (for autocannon)"
exit 1
fi
cleanup() {
lsof -ti :"$PORT" 2>/dev/null | xargs kill -9 2>/dev/null || true
}
trap cleanup EXIT
start_server() {
cleanup
sleep 0.5
PORT=$PORT node "$MINIMAL_SERVER" &>/dev/null &
SERVER_PID=$!
# Wait for server to be ready
local retries=0
while ! curl -sf "http://localhost:$PORT" >/dev/null 2>&1; do
retries=$((retries + 1))
if [ "$retries" -gt 30 ]; then
echo "ERROR: Server failed to start after 15s"
exit 1
fi
sleep 0.5
done
}
stop_server() {
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
cleanup
sleep 1
}
warmup() {
echo " Warming up ($WARMUP_REQS requests)..."
for i in $(seq 1 "$WARMUP_REQS"); do
curl -sf "http://localhost:$PORT" >/dev/null 2>&1 || true
done
sleep 0.5
}
run_phase() {
local label="$1"
local connections="$2"
echo ""
echo " --- $label (${DURATION}s, c=$connections) ---"
local result
result=$(npx autocannon -d "$DURATION" -c "$connections" -j "http://localhost:$PORT" 2>/dev/null)
node -e "
const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
const r = d.requests;
const l = d.latency;
console.log(' Throughput:');
console.log(' avg: ' + r.average + ' req/s');
console.log(' mean: ' + r.mean + ' req/s');
console.log(' total: ' + r.total + ' requests in ${DURATION}s');
console.log(' Latency:');
console.log(' avg: ' + l.average.toFixed(2) + ' ms');
console.log(' p50: ' + l.p50.toFixed(2) + ' ms');
console.log(' p90: ' + l.p90.toFixed(2) + ' ms');
console.log(' p99: ' + l.p99.toFixed(2) + ' ms');
console.log(' max: ' + l.max.toFixed(2) + ' ms');
" <<< "$result"
}
run_benchmark() {
local mode="$1"
echo ""
echo "============================================"
echo " $mode"
echo "============================================"
start_server
warmup
run_phase "Single client" 1
run_phase "Under load" 100
stop_server
}
echo "Benchmark: web streams vs node streams"
echo "======================================="
echo "Duration: ${DURATION}s per phase | Warmup: ${WARMUP_REQS} reqs"
echo "Server: minimal-server (minimalMode: true)"
# --- Web Streams (default) ---
cat > next.config.js <<'CONF'
module.exports = {}
CONF
echo ""
echo "Building (web streams)..."
node "$NEXT_BIN" build &>/dev/null
run_benchmark "Web Streams (default)"
# --- Node Streams ---
cat > next.config.js <<'CONF'
module.exports = {
experimental: {
useNodeStreams: true,
},
}
CONF
echo ""
echo "Building (node streams)..."
node "$NEXT_BIN" build &>/dev/null
run_benchmark "Node Streams (useNodeStreams: true)"
# Restore config
cat > next.config.js <<'CONF'
module.exports = {}
CONF
echo ""
echo "Done."

View File

@@ -0,0 +1 @@
module.exports = {}

View File

@@ -0,0 +1,3 @@
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}

View File

@@ -0,0 +1,7 @@
export default () => 'Hello World'
export function getServerSideProps() {
return {
props: {},
}
}