@thomas.f/prnext 0.1.17-alpha → 0.1.19-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.
Files changed (202) hide show
  1. package/README.md +27 -868
  2. package/build/actions.mjs +27 -15
  3. package/build/analyze.mjs +180 -24
  4. package/build/app-config.mjs +13 -0
  5. package/build/app-static.mjs +34 -12
  6. package/build/app-styles.mjs +79 -0
  7. package/build/app.mjs +122 -46
  8. package/build/bundle-runtime.mjs +22 -9
  9. package/build/cache-components.mjs +1 -1
  10. package/build/cache-handlers.mjs +1 -1
  11. package/build/compact-css.mjs +53 -0
  12. package/build/compilation-cache.mjs +269 -0
  13. package/build/compilation-store.mjs +142 -0
  14. package/build/compiler.mjs +34 -10
  15. package/build/config.mjs +34 -3
  16. package/build/create.mjs +239 -0
  17. package/build/css-modules.mjs +56 -12
  18. package/build/deployment-assets.mjs +89 -0
  19. package/build/deployment-config.mjs +18 -0
  20. package/build/dev-css-assets.mjs +173 -0
  21. package/build/dev-css-update.mjs +18 -14
  22. package/build/dev-dependencies.mjs +1 -1
  23. package/build/dev-discovery.mjs +3 -3
  24. package/build/dev-lazy-build.mjs +77 -0
  25. package/build/dev.mjs +15 -8
  26. package/build/dynamic.mjs +14 -7
  27. package/build/edge.mjs +3 -3
  28. package/build/fonts.mjs +1 -1
  29. package/build/framework-imports.mjs +15 -5
  30. package/build/html-only-config.mjs +53 -0
  31. package/build/html-only-graph.mjs +67 -0
  32. package/build/incremental.mjs +112 -18
  33. package/build/index.mjs +90 -28
  34. package/build/instrumentation.mjs +30 -0
  35. package/build/lazy-dynamic-imports.mjs +137 -0
  36. package/build/metadata-routes.mjs +1 -1
  37. package/build/migrate.mjs +4 -4
  38. package/build/migration-audit.mjs +19 -31
  39. package/build/migration-imports.mjs +245 -0
  40. package/build/migration-scenarios-runner.mjs +73 -0
  41. package/build/migration-scenarios.mjs +72 -0
  42. package/build/native-discovery.mjs +65 -5
  43. package/build/native-packages.mjs +2 -0
  44. package/build/native-type-config.mjs +37 -0
  45. package/build/npm-packages.mjs +1 -0
  46. package/build/persistent-cache.mjs +18 -3
  47. package/build/precompress.mjs +1 -1
  48. package/build/prerender-cache.mjs +70 -0
  49. package/build/prerender-config.mjs +29 -0
  50. package/build/prerender-pages.mjs +19 -9
  51. package/build/prerender-pool.mjs +165 -0
  52. package/build/prerender-process-worker.mjs +58 -0
  53. package/build/prerender-worker.mjs +5 -5
  54. package/build/production-builder.mjs +59 -10
  55. package/build/react-compiler-report.mjs +225 -0
  56. package/build/react-compiler.mjs +139 -0
  57. package/build/runtime-contract.mjs +2 -2
  58. package/build/standalone.mjs +21 -3
  59. package/build/static-export.mjs +4 -4
  60. package/build/styles.mjs +6 -4
  61. package/build/transform.mjs +1 -1
  62. package/build/typed-routes.mjs +4 -0
  63. package/build/typescript-dev.mjs +35 -8
  64. package/build/typescript-native-worker.mjs +55 -0
  65. package/build/typescript-native.mjs +18 -0
  66. package/build/typescript-toolchain.mjs +19 -0
  67. package/build/typescript.mjs +6 -4
  68. package/build/webpack-graph.mjs +19 -6
  69. package/build/worker-memory.mjs +9 -0
  70. package/cli.mjs +70 -5
  71. package/compat/activity-cache.cjs +26 -0
  72. package/compat/after.cjs +6 -4
  73. package/compat/app-dynamic.cjs +12 -1
  74. package/compat/app-layout-context.cjs +52 -2
  75. package/compat/base64.cjs +10 -0
  76. package/compat/cache-handlers.cjs +15 -3
  77. package/compat/cache-wire.cjs +28 -0
  78. package/compat/cache.cjs +2 -1
  79. package/compat/cache.d.cts +4 -0
  80. package/compat/cookies.cjs +21 -5
  81. package/compat/data-cache.cjs +12 -8
  82. package/compat/flight-delta.cjs +152 -0
  83. package/compat/headers.cjs +4 -2
  84. package/compat/incremental-cache.cjs +20 -7
  85. package/compat/index.d.ts +69 -4
  86. package/compat/link.cjs +13 -10
  87. package/compat/navigation-authorization.cjs +9 -0
  88. package/compat/navigation-stages.cjs +19 -0
  89. package/compat/offline-store.cjs +11 -0
  90. package/compat/offline.cjs +5 -0
  91. package/compat/offline.d.cts +2 -0
  92. package/compat/redis-cache.cjs +201 -0
  93. package/compat/redis-cache.d.cts +37 -0
  94. package/compat/server-primitives.cjs +31 -11
  95. package/compat/server.d.cts +15 -2
  96. package/compat/static-generation.cjs +7 -0
  97. package/compat/use-cache.cjs +3 -0
  98. package/docs/ai/compatibility.md +248 -2
  99. package/docs/ai/data.md +165 -5
  100. package/docs/ai/deployment.md +158 -0
  101. package/docs/ai/quickstart.md +29 -4
  102. package/docs/ai/routing.md +93 -0
  103. package/docs/ai/troubleshooting.md +116 -2
  104. package/package.json +40 -9
  105. package/runtime/action-client.mjs +10 -4
  106. package/runtime/action-server.mjs +2 -0
  107. package/runtime/app-client.mjs +316 -92
  108. package/runtime/app-content.mjs +4 -3
  109. package/runtime/app-partial-client.mjs +3 -0
  110. package/runtime/app-partial.mjs +1 -1
  111. package/runtime/app-prefetch-constants.mjs +4 -0
  112. package/runtime/app-prefetch.mjs +2 -3
  113. package/runtime/app-render-key.mjs +5 -0
  114. package/runtime/app-render.mjs +88 -28
  115. package/runtime/app-routing.mjs +22 -9
  116. package/runtime/app-static.mjs +18 -8
  117. package/runtime/app-stream-html.mjs +10 -53
  118. package/runtime/app-style-selection.mjs +34 -0
  119. package/runtime/app-styles.mjs +154 -0
  120. package/runtime/atomic-file.mjs +27 -0
  121. package/runtime/cache-components-rsc.mjs +7 -2
  122. package/runtime/cache-request.mjs +2 -1
  123. package/runtime/deployment-client.mjs +19 -0
  124. package/runtime/dev-client.mjs +13 -3
  125. package/runtime/dev-compiler-broker.mjs +42 -0
  126. package/runtime/dev-file-changes.mjs +123 -8
  127. package/runtime/dev-indicator.mjs +8 -3
  128. package/runtime/dev-lazy-imports.mjs +121 -0
  129. package/runtime/dev-lazy-staging.mjs +14 -0
  130. package/runtime/dev-lazy-tool.mjs +16 -0
  131. package/runtime/dev-style-retention.mjs +15 -0
  132. package/runtime/development.mjs +83 -25
  133. package/runtime/document.mjs +1 -1
  134. package/runtime/edge.mjs +6 -5
  135. package/runtime/fetch-cache.mjs +10 -8
  136. package/runtime/flight-delta.mjs +74 -0
  137. package/runtime/flight-tap.mjs +28 -0
  138. package/runtime/fs.mjs +15 -8
  139. package/runtime/html-only.mjs +27 -0
  140. package/runtime/http.mjs +2 -0
  141. package/runtime/incremental-cache.mjs +25 -4
  142. package/runtime/instrumentation.mjs +49 -0
  143. package/runtime/lazy-import-client.mjs +38 -0
  144. package/runtime/navigation-recovery.mjs +36 -0
  145. package/runtime/navigation.mjs +7 -0
  146. package/runtime/node-html-stream.mjs +47 -0
  147. package/runtime/pages-client.mjs +14 -7
  148. package/runtime/pages-navigation.mjs +48 -63
  149. package/runtime/prefetch-scheduler.mjs +110 -0
  150. package/runtime/profile.mjs +14 -0
  151. package/runtime/profiles.json +2 -2
  152. package/runtime/render.mjs +3 -0
  153. package/runtime/route-pattern.mjs +44 -0
  154. package/runtime/rsc-worker.mjs +34 -12
  155. package/runtime/trace.mjs +78 -0
  156. package/runtime/watch-project.mjs +19 -15
  157. package/runtime/worker.mjs +70 -26
  158. package/vendor/nft/LICENSE +7 -0
  159. package/vendor/nft/README.md +16 -0
  160. package/vendor/nft/out/analyze.d.ts +8 -0
  161. package/vendor/nft/out/analyze.js +1216 -0
  162. package/vendor/nft/out/analyze.js.map +1 -0
  163. package/vendor/nft/out/cli.d.ts +2 -0
  164. package/vendor/nft/out/cli.js +94 -0
  165. package/vendor/nft/out/cli.js.map +1 -0
  166. package/vendor/nft/out/fs.d.ts +22 -0
  167. package/vendor/nft/out/fs.js +106 -0
  168. package/vendor/nft/out/fs.js.map +1 -0
  169. package/vendor/nft/out/index.d.ts +4 -0
  170. package/vendor/nft/out/index.js +25 -0
  171. package/vendor/nft/out/index.js.map +1 -0
  172. package/vendor/nft/out/node-file-trace.d.ts +41 -0
  173. package/vendor/nft/out/node-file-trace.js +380 -0
  174. package/vendor/nft/out/node-file-trace.js.map +1 -0
  175. package/vendor/nft/out/resolve-dependency.d.ts +6 -0
  176. package/vendor/nft/out/resolve-dependency.js +427 -0
  177. package/vendor/nft/out/resolve-dependency.js.map +1 -0
  178. package/vendor/nft/out/types.d.ts +66 -0
  179. package/vendor/nft/out/types.js +2 -0
  180. package/vendor/nft/out/types.js.map +1 -0
  181. package/vendor/nft/out/utils/ast-helpers.js +49 -0
  182. package/vendor/nft/out/utils/ast-helpers.js.map +1 -0
  183. package/vendor/nft/out/utils/binary-locators.js +88 -0
  184. package/vendor/nft/out/utils/binary-locators.js.map +1 -0
  185. package/vendor/nft/out/utils/get-package-base.js +30 -0
  186. package/vendor/nft/out/utils/get-package-base.js.map +1 -0
  187. package/vendor/nft/out/utils/interop-require.js +24 -0
  188. package/vendor/nft/out/utils/interop-require.js.map +1 -0
  189. package/vendor/nft/out/utils/node-version.js +10 -0
  190. package/vendor/nft/out/utils/node-version.js.map +1 -0
  191. package/vendor/nft/out/utils/sharedlib-emit.js +33 -0
  192. package/vendor/nft/out/utils/sharedlib-emit.js.map +1 -0
  193. package/vendor/nft/out/utils/special-cases.js +347 -0
  194. package/vendor/nft/out/utils/special-cases.js.map +1 -0
  195. package/vendor/nft/out/utils/static-eval.js +579 -0
  196. package/vendor/nft/out/utils/static-eval.js.map +1 -0
  197. package/vendor/nft/out/utils/types.js +2 -0
  198. package/vendor/nft/out/utils/types.js.map +1 -0
  199. package/vendor/nft/out/utils/wrappers.js +659 -0
  200. package/vendor/nft/out/utils/wrappers.js.map +1 -0
  201. package/vendor/nft/package.json +4 -0
  202. package/vendor/nft/upstream.json +51 -0
@@ -20,6 +20,14 @@ segments and `pages/api/`. Existing `getServerSideProps`, `getStaticProps` and
20
20
  belong in an App Router page. Check a specific advanced routing feature against
21
21
  the installed implementation rather than assuming complete Next.js parity.
22
22
 
23
+ App styles follow the page and its layout scopes instead of loading every
24
+ page's stylesheet globally. Shared layout sheets are reused, and navigation
25
+ loads the next page's sheets before committing its content. Keep shared global
26
+ rules in the common layout and use CSS Modules for component-specific selectors.
27
+ Do not rely on a sibling page's CSS being present. Loading/error/default and
28
+ parallel-route branches can share a route's style plan; test their cascade as
29
+ well as ordinary forward and back navigation in a production build.
30
+
23
31
  ## Dynamic segments
24
32
 
25
33
  `app/products/[slug]/page.tsx` matches `/products/example`. App `params` and
@@ -80,6 +88,9 @@ Client Components can participate in server rendering. Read `window`,
80
88
  `useEffect`, not unconditionally during render. Server and first browser render
81
89
  must agree. Use `.ts` or `.tsx` for `'use client'` and `'use server'` boundaries;
82
90
  PRNext rejects those directives in `.mts`/`.cts` instead of silently misbundling.
91
+ The migration audit reports these unsupported boundaries too. It also checks
92
+ `server-only` and `client-only` markers through imported helpers, respecting
93
+ module-level Server Action boundaries and Node Route Handlers.
83
94
 
84
95
  ## Navigation and typed routes
85
96
 
@@ -94,6 +105,55 @@ Client Component. Pages `useRouter` comes from `next/router`; they are different
94
105
  contracts. Server code can call `redirect()` or `notFound()` from
95
106
  `next/navigation`; let their control-flow exceptions reach the framework.
96
107
 
108
+ Production link prefetching prioritizes keyboard focus, hover and touch over
109
+ links entering the viewport. Both routers bound speculative work; an actual
110
+ navigation takes priority. Data saver, offline/2G connections and hidden tabs
111
+ disable speculation, while slower connections restrict it to intent. Browsers
112
+ without connection information retain bounded prefetching. `prefetch={false}`
113
+ disables Link speculation, including hover and focus. None of these policies
114
+ blocks a real click or changes authorization and private-data checks. App Link
115
+ automatic prefetching retains its existing partial-rendering requirement.
116
+ Set `prefetch={true}` to warm the full destination explicitly in an ordinary
117
+ App Router application without `cacheComponents`. The same network limits
118
+ apply, and development does not prefetch. Full prefetch warms modules and data;
119
+ the click still sends a fresh server request before showing the destination.
120
+ This includes prerendered pages whose access is controlled by a proxy: a
121
+ prefetched response cannot authorize a later navigation after an HttpOnly
122
+ cookie changes. Leave the prop unset to keep automatic behavior, or use `false`
123
+ to disable speculation.
124
+
125
+ ### Connection loss during App navigation
126
+
127
+ App navigation retries transport failures of its GET request within a 30-second
128
+ budget and at most three attempts. While disconnected, the current page and its
129
+ mounted state remain visible. A newer navigation cancels the older attempt.
130
+ Reconnection issues a fresh request with the current cookies; it does not serve
131
+ a saved private response. Application errors and deployment mismatches retain
132
+ their existing handling. Speculative prefetches are not queued offline.
133
+
134
+ For an optional application-owned connection indicator:
135
+
136
+ ```tsx
137
+ 'use client';
138
+ import { useOffline } from '@thomas.f/prnext/offline';
139
+
140
+ export default function ConnectionStatus() {
141
+ const offline = useOffline();
142
+ return offline ? <p role="status">Waiting for a connection…</p> : null;
143
+ }
144
+ ```
145
+
146
+ The hook reports browser offline status and pending navigation recovery, not a
147
+ guarantee that a server is reachable. Exhausted network recovery preserves the
148
+ page and dispatches `prnext:navigation-error` on `window`, with `detail.message`
149
+ for an application-owned retry notice. This recovery applies to App navigation;
150
+ it does not add offline Pages routing, a service worker or persistent storage.
151
+
152
+ Server Actions and other POSTs are **never automatically replayed**. If a mutation
153
+ loses its response, it may already have run: keep the user's input and verify its
154
+ result before offering an explicit retry. A full reload still loses ordinary
155
+ in-memory state; persist drafts deliberately if they must survive reloads.
156
+
97
157
  With `typedRoutes: true`, `prnext typegen` writes a discovered route registry.
98
158
  For the dynamic page above, this materializes an encoded URL:
99
159
 
@@ -112,6 +172,39 @@ parameters, separators and dot segments. Add query strings through
112
172
  Generated route checking is PRNext's registry, not the Next.js language-service
113
173
  plugin.
114
174
 
175
+ ## Retained App pages
176
+
177
+ App layout branches retain inactive UI through React Activity. Effects stop
178
+ while hidden, and returning to an authorized destination restores its mounted
179
+ form state. The shared default budget is four inactive branches for two minutes,
180
+ not four at every nesting level. It is an entry/time limit, not a byte-level RAM
181
+ guarantee. It applies within a mounted layout; a new root layout loads a document.
182
+
183
+ ```js
184
+ export default {
185
+ navigationCache: { maxEntries: 3, ttlMs: 60000, authCookies: ['session'] },
186
+ };
187
+ ```
188
+
189
+ Use `navigationCache: false` to disable retention. Server Actions, `router.refresh()`
190
+ and observed cookie/authorization changes discard inactive branches while keeping
191
+ the current page's client state. Back/forward navigation requests fresh Flight
192
+ before revealing a retained destination. Cache hits do not bypass authorization.
193
+ After a custom authentication request outside Server Actions, call
194
+ `router.refresh()`. A browser integration may also dispatch
195
+ `window.dispatchEvent(new Event('prnext:invalidate-navigation'))` to refresh and
196
+ clear retained/prefetched state. This is in-memory UI retention, not offline
197
+ storage or mutation replay.
198
+
199
+ By default, cookie changes invalidate inactive branches while ordinary refresh
200
+ keeps the active component state. Set `authCookies` to the application's actual
201
+ session cookie names to also reset active branches when those credentials change.
202
+ Unrelated preference cookies then do not affect retention. Authorization headers
203
+ remain part of the identity. Identity is checked in each branch's authorized
204
+ request context, including restored parallel slots. In development, the private
205
+ identity key remains stable across Fast Refresh; build-time action-key rotation
206
+ does not discard the active editor state.
207
+
115
208
  ## Route Handlers
116
209
 
117
210
  An App Route Handler exports HTTP methods and returns a Web `Response` or
@@ -2,6 +2,70 @@
2
2
 
3
3
  [AI documentation index](../../AI.md)
4
4
 
5
+ ## Compile large client imports only when used in development
6
+
7
+ For App Router applications, the explicit experimental option below keeps
8
+ literal client `import()` targets outside the initial browser graph. It defers
9
+ their transformation and compilation, rather than only downloading an already
10
+ compiled chunk later.
11
+
12
+ ```js
13
+ // prnext.config.mjs
14
+ export default {
15
+ experimental: { lazyDynamicImports: true }
16
+ };
17
+ ```
18
+
19
+ The option affects `prnext dev` only. Production keeps its ordinary dynamic
20
+ chunks and does not use a development compilation endpoint. SSR also keeps its
21
+ normal behavior. A `next/dynamic` component with `{ ssr: false }` is a useful
22
+ candidate for an editor or other large browser-only feature; an import needed
23
+ by SSR still needs its server compilation.
24
+
25
+ On first use, the development server compiles the requested subgraph, publishes
26
+ its immutable assets, and loads its CSS before resolving the import. Already
27
+ loaded ESM dependencies are reused through their original module URLs, keeping
28
+ shared objects and live bindings. Once activated, the module participates in
29
+ subsequent JavaScript and stylesheet updates. A failed compilation can be
30
+ requested again after correcting its source.
31
+
32
+ Activated styles remain loaded for the generation, including when parallel
33
+ slots select their own styles. Prefer CSS Modules or selectors scoped to the
34
+ deferred feature when its global styles should not affect other components.
35
+
36
+ The initial scope is App Router applications using the native compiler, with
37
+ same-origin assets and no webpack hook or custom loaders. Literal imports from
38
+ project `.js`, `.jsx`, `.mjs`, `.cjs`, `.ts` and `.tsx` sources are eligible;
39
+ computed imports, import attributes, literal requests containing `?` or `#`,
40
+ imports inside installed packages and typed `.mts`/`.cts` helpers keep the
41
+ ordinary compiler behavior. The compiler keeps the distinct module identities
42
+ of those literal query and fragment imports. If an alias or a transitive
43
+ dependency introduces a resolved query or fragment suffix inside a deferred
44
+ graph, activation returns an explicit error
45
+ before reusing any shared export bridge. Disable the option for that graph;
46
+ query and fragment identities in deferred graphs are not currently supported.
47
+ The compiler does not silently duplicate a shared CommonJS dependency: that
48
+ case returns an explicit error. Convert that shared dependency to ESM or disable
49
+ the option.
50
+ Server Actions first introduced only by a deferred graph also require a static
51
+ import or the ordinary compiler, because the running server implementation
52
+ cannot be extended by publishing browser assets alone.
53
+
54
+ There are at most 128 registered imports and 4,096 static JavaScript dependency
55
+ identities per generation. Deferred assets have a cumulative 128 MiB budget per
56
+ active generation. Existing development request and generation limits still
57
+ apply. Public requests contain opaque registered IDs, never source filenames;
58
+ an unknown ID cannot initiate a deferred compilation. Static ESM export bridges
59
+ have their own startup cost, so measure your application's initial build and
60
+ first-use delay before keeping the option enabled.
61
+
62
+ Deferred JSON imports share their native ESM namespace and default object across
63
+ importers. Deferred assets are written outside the served directory and published
64
+ as complete immutable files. This experimental path requires hardlinks within
65
+ the development generation's filesystem; disable `lazyDynamicImports` if that
66
+ filesystem cannot create them. A failed activation keeps existing assets intact
67
+ and conservatively accounts for any publication whose outcome is uncertain.
68
+
5
69
  ## Collect a useful failure
6
70
 
7
71
  Read the installed version, command, working directory, Node version, manager,
@@ -54,11 +118,33 @@ repair. Verify the interactive result after the change.
54
118
 
55
119
  ## HMR and cache failures
56
120
 
121
+ When an Action overlaps a refresh or navigation, its mutation result remains
122
+ independent from whether its older render is applied. A newer interaction can
123
+ release a superseded development commit wait; it never replays the mutation.
124
+
125
+ For a development state publication failure, keep the private
126
+ `.prnext-dev/<session>/diagnostics/state-publication.json` receipt. It records the
127
+ operation phase, error code, bounded rename attempts and last published sequence,
128
+ without source contents or a full source path. Windows transient rename failures
129
+ are retried for up to two seconds; a permanent failure preserves the previous
130
+ complete state file. After a replacement runtime has activated, publication
131
+ failure still retires obsolete runtimes through the gateway and keeps the
132
+ existing three-generation snapshot bound. In-flight requests drain before
133
+ their old runtime closes. Record the actual code and phase instead of assuming
134
+ an antivirus or file watcher caused the lock.
135
+
57
136
  Development compiles requested routes and preserves state for compatible edits;
58
137
  config/environment, custom Document or incompatible module changes can reload
59
138
  the document. Production prerendering and compression are not development HMR.
60
139
  An unused route need not rebuild until requested.
61
140
 
141
+ Middleware and rewrites can select a cold destination after routing. PRNext
142
+ compiles that destination through its private development compiler and continues
143
+ the same request. It does not send an upload or action through middleware again.
144
+ Retained parallel branches are compiled together when their source is needed.
145
+ An error in an unrelated unopened route should not force that route into the
146
+ active graph. Safe mode remains available for full-graph comparisons.
147
+
62
148
  For a controlled diagnosis, stop only the development process you own and try:
63
149
 
64
150
  ```sh
@@ -66,12 +152,26 @@ prnext dev --safe
66
152
  ```
67
153
 
68
154
  Safe mode uses full builds and fresh workers. `PRNEXT_BUILD_CACHE=0` disables
69
- PRNext's compiler/build caches when set in the current process environment; use
155
+ PRNext's persistent compiler/build caches when set in the current process environment; use
70
156
  the syntax appropriate to the user's shell and restore the previous setting
71
- after the comparison. Optional cache-storage failures should fall back to work,
157
+ after the comparison. In-memory compiler/transform reuse is a separate layer.
158
+ Optional cache-storage failures should fall back to work,
72
159
  while genuine loader errors remain build failures. Do not delete every cache or
73
160
  lockfile as a first response, especially with another server running.
74
161
 
162
+ Production builds can reuse eligible compiled JavaScript graphs and CSS Module
163
+ outputs from the default CSS engine across processes through the private
164
+ `.prnext-cache` directory. The successful artifact's `compilation-cache-report.json` and the
165
+ programmatic build result's `compilationCache` report actual hits, misses and
166
+ bypasses. These are compilation diagnostics, not response-cache or latency
167
+ measurements. App graphs that discover actions or client boundaries, development
168
+ graphs, the explicit PostCSS engine and custom loader/PostCSS pipelines still
169
+ execute their compiler work.
170
+ HTML, Flight responses and private rendered data are not stored in this cache.
171
+ Changes to tracked dependencies, resolution candidates, options, environment
172
+ or framework identity invalidate eligible entries. Corrupt or unavailable cache
173
+ records fall back to compilation; `PRNEXT_BUILD_CACHE=0` disables their persistent reuse.
174
+
75
175
  For production observations:
76
176
 
77
177
  ```sh
@@ -85,6 +185,20 @@ exclude the full streaming body, and missing/dropped samples are not zero.
85
185
  `prnext analyze`, after building, rather than interpreting request time as
86
186
  compiler performance.
87
187
 
188
+ Initial-JS analysis includes required hydration imports and SSR-used dynamic
189
+ chunks. Schema 2 reports per-prerendered-path samples and the maximum size for
190
+ each compression metric; a route's file list can be the union of its samples.
191
+ Request-dependent or incomplete graphs are lower bounds. Their size budgets
192
+ fail as `initial-unknown`, even if that lower bound is small. Do not present it
193
+ as a complete measurement or a size saving. Rebuild old schema-1 baselines before
194
+ comparing them with schema 2. An opaque webpack graph is also marked incomplete.
195
+
196
+ For memoization questions, run `prnext compiler --json` after a successful build
197
+ with `reactCompiler` enabled. Inspect the affected function and its skip reason,
198
+ the reported graph coverage and cached-transform counts. An absent function in
199
+ an observed-transforms report is not proof that it was optimized or rejected.
200
+ Keep application behavior and hydration checks alongside this diagnostic.
201
+
88
202
  ## Connect the existing development MCP
89
203
 
90
204
  Start `prnext dev` in the application, then configure a compatible assistant to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thomas.f/prnext",
3
- "version": "0.1.17-alpha",
3
+ "version": "0.1.19-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",
@@ -41,7 +41,8 @@
41
41
  "runtime/",
42
42
  "compat/",
43
43
  "native/",
44
- "release/"
44
+ "release/",
45
+ "vendor/"
45
46
  ],
46
47
  "scripts": {
47
48
  "prepublishOnly": "node release/verify.mjs"
@@ -115,6 +116,14 @@
115
116
  "./headers": "./compat/headers.cjs",
116
117
  "./server": "./compat/server.cjs",
117
118
  "./cache": "./compat/cache.cjs",
119
+ "./cache/redis": {
120
+ "types": "./compat/redis-cache.d.cts",
121
+ "default": "./compat/redis-cache.cjs"
122
+ },
123
+ "./offline": {
124
+ "types": "./compat/offline.d.cts",
125
+ "default": "./compat/offline.cjs"
126
+ },
118
127
  "./constants": "./compat/constants.cjs"
119
128
  },
120
129
  "dependencies": {
@@ -124,38 +133,60 @@
124
133
  "@babel/traverse": "^7.29.0",
125
134
  "@babel/types": "^7.29.0",
126
135
  "@edge-runtime/vm": "5.0.0",
127
- "@vercel/nft": "1.11.0",
136
+ "@jridgewell/trace-mapping": "0.3.31",
137
+ "@mapbox/node-pre-gyp": "2.0.3",
138
+ "@rollup/pluginutils": "5.4.0",
139
+ "acorn": "8.18.0",
140
+ "acorn-import-attributes": "1.9.5",
141
+ "async-sema": "3.1.1",
142
+ "babel-plugin-react-compiler": "1.0.0",
143
+ "bindings": "1.5.0",
128
144
  "browserslist": "4.29.0",
129
145
  "dotenv": "16.6.1",
130
146
  "dotenv-expand": "11.0.7",
131
147
  "esbuild": "^0.28.2",
148
+ "estree-walker": "2.0.2",
132
149
  "fontkit": "2.0.4",
150
+ "get-tsconfig": "4.14.3",
151
+ "glob": "14.0.2",
152
+ "graceful-fs": "4.2.11",
133
153
  "html-to-image": "1.11.13",
154
+ "jsonc-parser": "3.3.1",
134
155
  "lightningcss": "1.31.0",
135
156
  "loader-runner": "4.3.2",
157
+ "minimatch": "11.0.1",
158
+ "node-gyp-build": "4.8.4",
136
159
  "oxc-parser": "0.155.0",
137
160
  "path-to-regexp": "6.3.0",
138
161
  "picomatch": "4.0.7",
139
162
  "postcss": "8.5.28",
140
163
  "postcss-flexbugs-fixes": "5.0.2",
141
164
  "postcss-preset-env": "11.5.3",
165
+ "postcss-selector-parser": "7.1.6",
142
166
  "postcss-value-parser": "4.2.0",
143
167
  "react-refresh": "0.19.0",
168
+ "resolve-from": "5.0.0",
144
169
  "schema-utils": "4.3.3",
145
170
  "webpack": "5.111.1"
146
171
  },
147
172
  "peerDependencies": {
173
+ "@redis/client": "^6.3.0",
148
174
  "react": "19.3.1",
149
175
  "react-dom": "19.3.1",
150
176
  "react-server-dom-webpack": "19.3.1"
151
177
  },
178
+ "peerDependenciesMeta": {
179
+ "@redis/client": {
180
+ "optional": true
181
+ }
182
+ },
152
183
  "optionalDependencies": {
153
- "@thomas.f/prnext-win32-arm64-msvc": "0.1.17-alpha",
154
- "@thomas.f/prnext-win32-x64-msvc": "0.1.17-alpha",
155
- "prnext-darwin-arm64": "0.1.17-alpha",
156
- "prnext-darwin-x64": "0.1.17-alpha",
157
- "prnext-linux-arm64-gnu": "0.1.17-alpha",
158
- "prnext-linux-x64-gnu": "0.1.17-alpha"
184
+ "prnext-darwin-arm64": "0.1.19-alpha",
185
+ "prnext-darwin-x64": "0.1.19-alpha",
186
+ "prnext-linux-arm64-gnu": "0.1.19-alpha",
187
+ "prnext-linux-x64-gnu": "0.1.19-alpha",
188
+ "@thomas.f/prnext-win32-x64-msvc": "0.1.19-alpha",
189
+ "@thomas.f/prnext-win32-arm64-msvc": "0.1.19-alpha"
159
190
  },
160
191
  "engines": {
161
192
  "node": "^22.23.4 || ^24.22.1 || >=26.12.1"
@@ -1,19 +1,25 @@
1
- let referenceFactory;
2
- let transport;
1
+ // A newly opened route can move this helper into a different development ESM
2
+ // chunk. Its action proxies still belong to the already mounted application.
3
+ // Production keeps the ordinary per-graph module state.
4
+ const state = process.env.NODE_ENV === 'development'
5
+ ? globalThis[Symbol.for('prnext.development.server-actions')] ||= {}
6
+ : {};
3
7
 
4
8
  // App bootstrap installs the official Flight client after its module loader is
5
9
  // ready. Action proxy modules load through that same client graph afterwards.
6
10
  export function configureServerActions({ createServerReference, callServer }) {
7
- referenceFactory = createServerReference;
8
- transport = callServer;
11
+ state.referenceFactory = createServerReference;
12
+ state.transport = callServer;
9
13
  }
10
14
 
11
15
  export function callServer(id, args) {
16
+ const transport = state.transport;
12
17
  if (!transport) return Promise.reject(new Error('The PRNext Server Action transport is not initialized'));
13
18
  return transport(id, args);
14
19
  }
15
20
 
16
21
  export function createServerReference(id) {
22
+ const referenceFactory = state.referenceFactory;
17
23
  if (!referenceFactory) throw new Error('Server Action references must load after the PRNext Flight client');
18
24
  return referenceFactory(id, callServer);
19
25
  }
@@ -1,3 +1,4 @@
1
+ import {reportRequestError} from './instrumentation.mjs';
1
2
  import { decodeReply, decodeAction, decodeFormState, createTemporaryReferenceSet } from 'react-server-dom-webpack/server.node';
2
3
  import { pathToFileURL } from 'node:url';
3
4
  import path from 'node:path';
@@ -126,6 +127,7 @@ export async function invokeAction(request) {
126
127
  } else if (navigation?.status === 404) {
127
128
  actionNotFound = true;
128
129
  } else {
130
+ reportRequestError(error,{routeType:'action'});
129
131
  console.error('[prnext]', error?.stack || error);
130
132
  actionError = errorPayload(error, request.production);
131
133
  failure = { message: error?.message || String(error), stack: error?.stack, digest: error?.digest };