@thomas.f/prnext 0.1.19-alpha → 0.1.21-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/app.mjs +46 -78
- package/build/build-lock.mjs +2 -71
- package/build/build-retention.mjs +119 -0
- package/build/build-timings.mjs +38 -0
- package/build/bundle-runtime.mjs +17 -16
- package/build/cache-command.mjs +31 -0
- package/build/check.mjs +41 -3
- package/build/compilation-cache.mjs +32 -12
- package/build/compilation-storage.mjs +190 -0
- package/build/compiler.mjs +5 -4
- package/build/config.mjs +23 -2
- package/build/create.mjs +1 -1
- package/build/css-modules.mjs +4 -0
- package/build/dev-action-graph.mjs +21 -0
- package/build/flight-summary.mjs +64 -0
- package/build/font-cache.mjs +9 -6
- package/build/font-files.mjs +1 -1
- package/build/index.mjs +57 -36
- package/build/inspect.mjs +3 -0
- package/build/inspection-summary.mjs +7 -2
- package/build/native-discovery.mjs +18 -6
- package/build/native-ppr.mjs +32 -0
- package/build/npm-packages.mjs +2 -2
- package/build/og.mjs +121 -1
- package/build/parallel-plan.mjs +55 -0
- package/build/persistent-cache.mjs +29 -24
- package/build/production-check.mjs +34 -0
- package/build/react-compiler-report.mjs +31 -8
- package/build/react-compiler.mjs +101 -10
- package/build/server-config.mjs +35 -0
- package/build/source-analysis.mjs +108 -5
- package/build/standalone-copy.mjs +48 -0
- package/build/standalone.mjs +2 -22
- package/build/static-adapter.mjs +7 -3
- package/build/transform-cache.mjs +17 -3
- package/build/transform.mjs +38 -6
- package/build/typescript-dev.mjs +3 -1
- package/cli.mjs +27 -5
- package/compat/app-layout-context.cjs +7 -3
- package/compat/diagnostics.cjs +5 -4
- package/compat/flight-delta.cjs +47 -12
- package/compat/index.d.ts +24 -1
- package/compat/navigation-authorization.cjs +8 -1
- package/compat/runtime-sample.cjs +56 -0
- package/compat/use-cache.cjs +5 -2
- package/docs/ai/compatibility.md +113 -10
- package/docs/ai/deployment.md +144 -0
- package/docs/ai/quickstart.md +5 -0
- package/docs/ai/troubleshooting.md +22 -0
- package/package.json +25 -22
- package/release/fontkit.mjs +31 -0
- package/release/verify.mjs +3 -0
- package/runtime/api.mjs +5 -2
- package/runtime/app-client.mjs +246 -54
- package/runtime/app-partial.mjs +2 -10
- package/runtime/app-prefetch.mjs +2 -2
- package/runtime/app-render.mjs +42 -13
- package/runtime/app-stream-channel.mjs +20 -6
- package/runtime/app-stream-html.mjs +30 -11
- package/runtime/app-styles.mjs +22 -4
- package/runtime/cache-components-rsc.mjs +26 -6
- package/runtime/cache-result.mjs +58 -0
- package/runtime/compile-cache-retention.mjs +53 -0
- package/runtime/compile-cache.mjs +28 -1
- package/runtime/dev-client.mjs +32 -8
- package/runtime/dev-compiler-broker.mjs +20 -23
- package/runtime/dev-gateway.mjs +23 -6
- package/runtime/dev-route-selection.mjs +64 -0
- package/runtime/dev-runtime-pool.mjs +3 -2
- package/runtime/dev-runtime-spare.mjs +1 -1
- package/runtime/dev-session-retention.mjs +154 -0
- package/runtime/development-flight.mjs +59 -0
- package/runtime/development-queue.mjs +33 -0
- package/runtime/development.mjs +37 -16
- package/runtime/env.mjs +9 -0
- package/runtime/flight-delta.mjs +31 -5
- package/runtime/flight-diagnostics.mjs +48 -0
- package/runtime/flight-tap.mjs +10 -5
- package/runtime/html-envelope.mjs +34 -0
- package/runtime/loopback-rpc.mjs +92 -0
- package/runtime/native-ppr.mjs +88 -0
- package/runtime/og/NOTICE.txt +1 -1
- package/runtime/og/index.node.mjs +76 -31216
- package/runtime/og/upstream.json +115 -0
- package/runtime/persistent/client.mjs +5 -3
- package/runtime/persistent/common.mjs +7 -18
- package/runtime/persistent/daemon.mjs +4 -12
- package/runtime/persistent/health.mjs +58 -0
- package/runtime/persistent/native-proxy.mjs +1 -1
- package/runtime/persistent/watchdog.mjs +12 -27
- package/runtime/prewarm.mjs +35 -0
- package/runtime/project-lock.mjs +71 -0
- package/runtime/request-transport.mjs +112 -32
- package/runtime/rsc-worker.mjs +58 -8
- package/runtime/storage-path.mjs +36 -0
- package/runtime/trace.mjs +44 -4
- package/runtime/worker.mjs +37 -17
- package/vendor/fontkit/NOTICE.txt +5 -0
- package/vendor/fontkit/SOURCE-NOTICES.txt +209 -0
- package/vendor/fontkit/index.mjs +3 -0
- package/vendor/fontkit/licenses/@swc__helpers/LICENSE +201 -0
- package/vendor/fontkit/licenses/base64-js/LICENSE +21 -0
- package/vendor/fontkit/licenses/brotli/readme.md +61 -0
- package/vendor/fontkit/licenses/clone/LICENSE +18 -0
- package/vendor/fontkit/licenses/dfa/README.md +83 -0
- package/vendor/fontkit/licenses/fast-deep-equal/LICENSE +21 -0
- package/vendor/fontkit/licenses/fontkit/README.md +266 -0
- package/vendor/fontkit/licenses/restructure/LICENSE +21 -0
- package/vendor/fontkit/licenses/tiny-inflate/LICENSE +21 -0
- package/vendor/fontkit/licenses/tslib/LICENSE.txt +12 -0
- package/vendor/fontkit/licenses/unicode-properties/LICENSE +8 -0
- package/vendor/fontkit/licenses/unicode-trie/LICENSE +8 -0
- package/vendor/fontkit/upstream.json +215 -0
|
@@ -185,6 +185,28 @@ exclude the full streaming body, and missing/dropped samples are not zero.
|
|
|
185
185
|
`prnext analyze`, after building, rather than interpreting request time as
|
|
186
186
|
compiler performance.
|
|
187
187
|
|
|
188
|
+
The `flight` section of `prnext inspect --json` groups observed App Router
|
|
189
|
+
payload sizes by route pattern and render phase. `flightP95Bytes` is the
|
|
190
|
+
uncompressed Flight size for completed samples; `responseP95Bytes` is the
|
|
191
|
+
uncompressed application output yielded by the HTML renderer. Cancelled, failed
|
|
192
|
+
and timed-out samples remain visible separately and do not count as complete
|
|
193
|
+
payloads. RSC and SSR can observe the same Flight stream: never add their sizes
|
|
194
|
+
or request counts. `modelReadyP95Ms`, `shellReadyP95Ms` and `durationP95Ms`
|
|
195
|
+
include rendering, application work and asynchronous waits, not isolated
|
|
196
|
+
encoder/decoder CPU. Missing data stays `null`. The OTLP/JSON view includes
|
|
197
|
+
`prnext.flight.response.size` in bytes with separate render-phase attributes.
|
|
198
|
+
|
|
199
|
+
Large server-generated presentation trees can produce much more Flight data
|
|
200
|
+
than compact public props. For a pure table, consider a small explicit
|
|
201
|
+
`'use client'` presentation component receiving only the public fields it needs.
|
|
202
|
+
Its initial document can still render on the server, while its implementation
|
|
203
|
+
also joins the browser bundle. Measure the resulting Flight/HTML sizes,
|
|
204
|
+
JavaScript transfer, browser execution and hydration together. Keep database
|
|
205
|
+
access, credentials and private server logic outside that boundary. A count-only
|
|
206
|
+
synthetic table does not predict savings for real row data; converting arbitrary
|
|
207
|
+
Server Components automatically is not a safe optimization. Inspecting a route
|
|
208
|
+
does not automatically rewrite it, enable caching or change its privacy policy.
|
|
209
|
+
|
|
188
210
|
Initial-JS analysis includes required hydration imports and SSR-used dynamic
|
|
189
211
|
chunks. Schema 2 reports per-prerendered-path samples and the maximum size for
|
|
190
212
|
each compression metric; a route's file list can be the union of its samples.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thomas.f/prnext",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21-alpha",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Experimental Rust-powered runtime for Next.js apps, React and npm",
|
|
6
6
|
"homepage": "https://prnext.dev",
|
|
@@ -135,58 +135,61 @@
|
|
|
135
135
|
"@edge-runtime/vm": "5.0.0",
|
|
136
136
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
137
137
|
"@mapbox/node-pre-gyp": "2.0.3",
|
|
138
|
-
"@rollup/pluginutils": "5.
|
|
139
|
-
"acorn": "8.
|
|
138
|
+
"@rollup/pluginutils": "5.5.1",
|
|
139
|
+
"acorn": "8.19.0",
|
|
140
140
|
"acorn-import-attributes": "1.9.5",
|
|
141
141
|
"async-sema": "3.1.1",
|
|
142
142
|
"babel-plugin-react-compiler": "1.0.0",
|
|
143
143
|
"bindings": "1.5.0",
|
|
144
|
-
"browserslist": "4.29.
|
|
145
|
-
"dotenv": "
|
|
144
|
+
"browserslist": "4.29.5",
|
|
145
|
+
"dotenv": "18.0.9",
|
|
146
146
|
"dotenv-expand": "11.0.7",
|
|
147
147
|
"esbuild": "^0.28.2",
|
|
148
148
|
"estree-walker": "2.0.2",
|
|
149
|
-
"fontkit": "2.0.4",
|
|
150
149
|
"get-tsconfig": "4.14.3",
|
|
151
|
-
"glob": "14.0.
|
|
150
|
+
"glob": "14.0.3",
|
|
152
151
|
"graceful-fs": "4.2.11",
|
|
153
152
|
"html-to-image": "1.11.13",
|
|
154
153
|
"jsonc-parser": "3.3.1",
|
|
155
|
-
"lightningcss": "1.
|
|
154
|
+
"lightningcss": "1.33.0",
|
|
156
155
|
"loader-runner": "4.3.2",
|
|
157
|
-
"minimatch": "11.0.
|
|
156
|
+
"minimatch": "11.0.4",
|
|
158
157
|
"node-gyp-build": "4.8.4",
|
|
159
|
-
"oxc-parser": "0.
|
|
158
|
+
"oxc-parser": "0.156.0",
|
|
160
159
|
"path-to-regexp": "6.3.0",
|
|
161
160
|
"picomatch": "4.0.7",
|
|
162
|
-
"postcss": "8.5.
|
|
161
|
+
"postcss": "8.5.32",
|
|
163
162
|
"postcss-flexbugs-fixes": "5.0.2",
|
|
164
|
-
"postcss-preset-env": "11.
|
|
165
|
-
"postcss-selector-parser": "7.1.
|
|
163
|
+
"postcss-preset-env": "11.6.2",
|
|
164
|
+
"postcss-selector-parser": "7.1.7",
|
|
166
165
|
"postcss-value-parser": "4.2.0",
|
|
167
166
|
"react-refresh": "0.19.0",
|
|
168
167
|
"resolve-from": "5.0.0",
|
|
169
|
-
"schema-utils": "4.
|
|
170
|
-
"webpack": "5.
|
|
168
|
+
"schema-utils": "4.8.2",
|
|
169
|
+
"webpack": "5.112.2"
|
|
171
170
|
},
|
|
172
171
|
"peerDependencies": {
|
|
173
172
|
"@redis/client": "^6.3.0",
|
|
174
173
|
"react": "19.3.1",
|
|
175
174
|
"react-dom": "19.3.1",
|
|
176
|
-
"react-server-dom-webpack": "19.3.1"
|
|
175
|
+
"react-server-dom-webpack": "19.3.1",
|
|
176
|
+
"oxc-transform-react": "0.157.0"
|
|
177
177
|
},
|
|
178
178
|
"peerDependenciesMeta": {
|
|
179
179
|
"@redis/client": {
|
|
180
180
|
"optional": true
|
|
181
|
+
},
|
|
182
|
+
"oxc-transform-react": {
|
|
183
|
+
"optional": true
|
|
181
184
|
}
|
|
182
185
|
},
|
|
183
186
|
"optionalDependencies": {
|
|
184
|
-
"prnext-darwin-arm64": "0.1.
|
|
185
|
-
"prnext-darwin-x64": "0.1.
|
|
186
|
-
"prnext-linux-arm64-gnu": "0.1.
|
|
187
|
-
"prnext-linux-x64-gnu": "0.1.
|
|
188
|
-
"@thomas.f/prnext-win32-x64-msvc": "0.1.
|
|
189
|
-
"@thomas.f/prnext-win32-arm64-msvc": "0.1.
|
|
187
|
+
"prnext-darwin-arm64": "0.1.21-alpha",
|
|
188
|
+
"prnext-darwin-x64": "0.1.21-alpha",
|
|
189
|
+
"prnext-linux-arm64-gnu": "0.1.21-alpha",
|
|
190
|
+
"prnext-linux-x64-gnu": "0.1.21-alpha",
|
|
191
|
+
"@thomas.f/prnext-win32-x64-msvc": "0.1.21-alpha",
|
|
192
|
+
"@thomas.f/prnext-win32-arm64-msvc": "0.1.21-alpha"
|
|
190
193
|
},
|
|
191
194
|
"engines": {
|
|
192
195
|
"node": "^22.23.4 || ^24.22.1 || >=26.12.1"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto';
|
|
2
|
+
import {readFile, readdir} from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
|
|
6
|
+
const destination = fileURLToPath(new URL('../vendor/fontkit/', import.meta.url));
|
|
7
|
+
const digest = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
8
|
+
|
|
9
|
+
/** Validate the shipped inventory without loading fontkit or its build dependencies. */
|
|
10
|
+
export async function verifyVendoredFontkit(directory = destination) {
|
|
11
|
+
const provenance = JSON.parse(await readFile(path.join(directory, 'upstream.json'), 'utf8'));
|
|
12
|
+
if (provenance.schemaVersion !== 1 || provenance.name !== 'fontkit' || provenance.version !== '2.0.4'
|
|
13
|
+
|| provenance.tool?.name !== 'esbuild' || !provenance.files?.['index.mjs']
|
|
14
|
+
|| !provenance.files?.['NOTICE.txt'] || !provenance.files?.['SOURCE-NOTICES.txt']
|
|
15
|
+
|| !provenance.packages?.fontkit || !provenance.packages?.brotli) throw new Error('Incomplete fontkit provenance.');
|
|
16
|
+
const actual = [];
|
|
17
|
+
async function visit(directory, prefix = '') {
|
|
18
|
+
for (const entry of await readdir(directory, {withFileTypes: true})) {
|
|
19
|
+
const name = prefix + entry.name;
|
|
20
|
+
if (entry.isDirectory()) await visit(path.join(directory, entry.name), name + '/');
|
|
21
|
+
else if (!entry.isFile()) throw new Error('Vendored fontkit files must be regular files.');
|
|
22
|
+
else if (name !== 'upstream.json') actual.push(name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
await visit(directory);
|
|
26
|
+
if (JSON.stringify(actual.sort()) !== JSON.stringify(Object.keys(provenance.files).sort())) throw new Error('Vendored fontkit inventory changed.');
|
|
27
|
+
for (const name of actual) {
|
|
28
|
+
if (digest(await readFile(path.join(directory, name))) !== provenance.files[name]) throw new Error(`Vendored fontkit differs from its reviewed build: ${name}`);
|
|
29
|
+
}
|
|
30
|
+
return {version: provenance.version, files: actual.length, bytes: (await readFile(path.join(directory, 'index.mjs'))).length};
|
|
31
|
+
}
|
package/release/verify.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { packageRoot, packageManifest, platforms, sourceCheckout } from '../native/resolve.mjs';
|
|
5
5
|
import { verifyAiDocumentation } from './ai-docs.mjs';
|
|
6
|
+
import { verifyVendoredFontkit } from './fontkit.mjs';
|
|
6
7
|
|
|
7
8
|
export async function verifyPackage() {
|
|
8
9
|
const pkg = packageManifest;
|
|
@@ -27,6 +28,8 @@ export async function verifyPackage() {
|
|
|
27
28
|
}
|
|
28
29
|
await exported(pkg.exports);
|
|
29
30
|
await verifyAiDocumentation(packageRoot, pkg);
|
|
31
|
+
await verifyVendoredFontkit();
|
|
32
|
+
if (pkg.dependencies.fontkit || pkg.dependencies['oxc-transform-react'] || pkg.peerDependenciesMeta?.['oxc-transform-react']?.optional !== true) throw new Error('Fontkit must be bundled and the Oxc React compiler must remain an optional peer.');
|
|
30
33
|
await access(path.join(packageRoot, 'runtime/profiles.json'));
|
|
31
34
|
for (const name of ['index.node.mjs', 'resvg.wasm', 'hb.wasm', 'Geist-Regular.ttf', 'LICENSE', 'LICENSE.fflate', 'LICENSE.Geist', 'LICENSE.harfbuzzjs', 'LICENSE.satori', 'NOTICE.txt']) await access(path.join(packageRoot, 'runtime/og', name));
|
|
32
35
|
if (pkg.dependencies['@vercel/og'] || (await readFile(path.join(packageRoot, 'runtime/og/index.node.mjs'), 'utf8')).includes('fflate@0.7.3')) throw new Error('OG renderer still depends on vulnerable upstream fflate. Run scripts/prepare-og.mjs.');
|
package/runtime/api.mjs
CHANGED
|
@@ -195,7 +195,7 @@ async function runApiInner({ modulePath, route = {}, manifest = {}, production =
|
|
|
195
195
|
// IncomingMessage here duplicates URL, header and cookie work and allocates
|
|
196
196
|
// an unused Duplex. Keep the existing Pages request path unchanged.
|
|
197
197
|
const { request, bytes } = appHandler
|
|
198
|
-
? { bytes: Buffer.isBuffer(body) ? body : Buffer.from(body || '', 'base64') }
|
|
198
|
+
? { bytes: body instanceof ReadableStream ? body : Buffer.isBuffer(body) ? body : Buffer.from(body || '', 'base64') }
|
|
199
199
|
: createRequest({ url, originalUrl: requestOriginal?.href, params, method, headers, body });
|
|
200
200
|
if (!appHandler) {
|
|
201
201
|
request.draftMode = cacheContext.draftMode;
|
|
@@ -226,7 +226,10 @@ async function runApiInner({ modulePath, route = {}, manifest = {}, production =
|
|
|
226
226
|
throw abortError(lifecycle.controller.signal.reason);
|
|
227
227
|
}
|
|
228
228
|
const init = { method, headers, ...(lifecycle ? { signal: lifecycle.controller.signal } : {}) };
|
|
229
|
-
if (!['GET', 'HEAD'].includes(method) && bytes.length)
|
|
229
|
+
if (!['GET', 'HEAD'].includes(method) && (bytes instanceof ReadableStream || bytes.length)) {
|
|
230
|
+
init.body = bytes;
|
|
231
|
+
if (bytes instanceof ReadableStream) init.duplex = 'half';
|
|
232
|
+
}
|
|
230
233
|
const timeout = lifecycle && setTimeout(() => lifecycle.controller.abort(apiTimeoutError('response headers', timeoutMs)), timeoutMs);
|
|
231
234
|
timeout?.unref();
|
|
232
235
|
const pendingResponse = runRequestContext({ url, method, headers, params, production, cacheComponents: manifest.config?.cacheComponents, cacheLife: manifest.config?.cacheLife, cacheHandlers: manifest.config?.cacheHandlers, cacheHandler: manifest.config?.cacheHandler, cacheMaxMemorySize: manifest.config?.cacheMaxMemorySize, distDir: path.dirname(path.dirname(modulePath)), signal: lifecycle?.controller.signal || signal, previewModeId: manifest.previewModeId, basePath: manifest.config?.basePath || '', routePattern: route.pattern, cacheConfig: route.cacheConfig, phase: 'route', cacheState: cacheContext.cacheState, staticState: cacheContext.staticState, mutableCookies: true }, async () => {
|