vinext 1.0.0-beta.1 → 1.0.0-beta.3

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 (234) hide show
  1. package/README.md +10 -10
  2. package/dist/build/client-build-config.js +8 -1
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +19 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +35 -122
  9. package/dist/config/next-config.d.ts +15 -5
  10. package/dist/config/next-config.js +7 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-browser-entry.d.ts +4 -10
  14. package/dist/entries/app-browser-entry.js +20 -4
  15. package/dist/entries/app-rsc-entry.js +30 -9
  16. package/dist/entries/app-rsc-manifest.js +36 -0
  17. package/dist/entries/pages-client-entry.js +0 -1
  18. package/dist/entries/pages-server-entry.js +13 -5
  19. package/dist/index.js +194 -101
  20. package/dist/init-cloudflare.d.ts +3 -1
  21. package/dist/init-cloudflare.js +59 -5
  22. package/dist/init.d.ts +6 -4
  23. package/dist/init.js +20 -22
  24. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  25. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  26. package/dist/plugins/import-meta-url.js +17 -6
  27. package/dist/plugins/og-assets.js +1 -1
  28. package/dist/plugins/require-context.js +20 -15
  29. package/dist/plugins/transform-cache.d.ts +19 -0
  30. package/dist/plugins/transform-cache.js +36 -0
  31. package/dist/routing/app-route-graph.d.ts +27 -11
  32. package/dist/routing/app-route-graph.js +158 -22
  33. package/dist/routing/app-router.js +12 -6
  34. package/dist/routing/file-matcher.d.ts +11 -22
  35. package/dist/routing/file-matcher.js +21 -33
  36. package/dist/routing/pages-router.js +23 -29
  37. package/dist/routing/route-matching.d.ts +14 -1
  38. package/dist/routing/route-matching.js +13 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +7 -4
  41. package/dist/routing/route-trie.d.ts +5 -1
  42. package/dist/routing/route-trie.js +5 -2
  43. package/dist/server/api-handler.d.ts +2 -0
  44. package/dist/server/api-handler.js +3 -3
  45. package/dist/server/app-browser-entry.js +110 -37
  46. package/dist/server/app-browser-history-controller.d.ts +1 -1
  47. package/dist/server/app-browser-history-controller.js +3 -3
  48. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  49. package/dist/server/app-browser-navigation-controller.js +2 -2
  50. package/dist/server/app-browser-state.js +1 -1
  51. package/dist/server/app-browser-visible-commit.js +1 -1
  52. package/dist/server/app-fallback-renderer.d.ts +3 -0
  53. package/dist/server/app-fallback-renderer.js +4 -2
  54. package/dist/server/app-middleware.js +2 -1
  55. package/dist/server/app-page-boundary-render.d.ts +12 -1
  56. package/dist/server/app-page-boundary-render.js +84 -2
  57. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  58. package/dist/server/app-page-cache-finalizer.js +1 -1
  59. package/dist/server/app-page-cache.d.ts +2 -2
  60. package/dist/server/app-page-cache.js +16 -2
  61. package/dist/server/app-page-dispatch.d.ts +19 -2
  62. package/dist/server/app-page-dispatch.js +45 -23
  63. package/dist/server/app-page-element-builder.d.ts +9 -2
  64. package/dist/server/app-page-element-builder.js +144 -33
  65. package/dist/server/app-page-head.d.ts +56 -4
  66. package/dist/server/app-page-head.js +216 -85
  67. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  68. package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
  69. package/dist/server/app-page-probe.d.ts +4 -0
  70. package/dist/server/app-page-probe.js +6 -2
  71. package/dist/server/app-page-render.d.ts +2 -2
  72. package/dist/server/app-page-render.js +1 -1
  73. package/dist/server/app-page-request.d.ts +15 -0
  74. package/dist/server/app-page-request.js +134 -14
  75. package/dist/server/app-page-response.js +1 -1
  76. package/dist/server/app-page-route-wiring.d.ts +16 -0
  77. package/dist/server/app-page-route-wiring.js +254 -52
  78. package/dist/server/app-pages-bridge.d.ts +1 -1
  79. package/dist/server/app-pages-bridge.js +2 -1
  80. package/dist/server/app-post-middleware-context.d.ts +1 -1
  81. package/dist/server/app-post-middleware-context.js +1 -1
  82. package/dist/server/app-route-handler-cache.js +4 -0
  83. package/dist/server/app-route-handler-dispatch.js +40 -20
  84. package/dist/server/app-route-handler-execution.d.ts +6 -1
  85. package/dist/server/app-route-handler-execution.js +42 -16
  86. package/dist/server/app-route-handler-policy.d.ts +2 -0
  87. package/dist/server/app-route-handler-policy.js +3 -3
  88. package/dist/server/app-route-handler-response.js +1 -1
  89. package/dist/server/app-route-module-loader.d.ts +9 -1
  90. package/dist/server/app-route-module-loader.js +4 -0
  91. package/dist/server/app-router-entry.js +6 -3
  92. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  93. package/dist/server/app-rsc-errors.d.ts +1 -1
  94. package/dist/server/app-rsc-errors.js +22 -2
  95. package/dist/server/app-rsc-handler.d.ts +10 -5
  96. package/dist/server/app-rsc-handler.js +73 -33
  97. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  98. package/dist/server/app-rsc-request-normalization.js +8 -2
  99. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  100. package/dist/server/app-rsc-response-finalizer.js +5 -11
  101. package/dist/server/app-rsc-route-matching.d.ts +29 -0
  102. package/dist/server/app-rsc-route-matching.js +93 -11
  103. package/dist/server/app-segment-config.js +13 -3
  104. package/dist/server/app-server-action-execution.d.ts +3 -1
  105. package/dist/server/app-server-action-execution.js +9 -7
  106. package/dist/server/app-ssr-entry.js +6 -6
  107. package/dist/server/app-ssr-stream.d.ts +1 -7
  108. package/dist/server/app-ssr-stream.js +2 -10
  109. package/dist/server/cache-control.d.ts +2 -2
  110. package/dist/server/cache-control.js +2 -1
  111. package/dist/server/config-headers.d.ts +24 -0
  112. package/dist/server/config-headers.js +52 -0
  113. package/dist/server/dev-initial-server-error.d.ts +1 -1
  114. package/dist/server/dev-server.d.ts +3 -1
  115. package/dist/server/dev-server.js +170 -321
  116. package/dist/server/headers.d.ts +2 -2
  117. package/dist/server/headers.js +4 -3
  118. package/dist/server/isr-cache.d.ts +11 -34
  119. package/dist/server/isr-cache.js +33 -43
  120. package/dist/server/isr-decision.d.ts +2 -2
  121. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  122. package/dist/server/middleware-matcher-pattern.js +219 -0
  123. package/dist/server/middleware-matcher.d.ts +2 -7
  124. package/dist/server/middleware-matcher.js +13 -60
  125. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  126. package/dist/server/middleware-path-to-regexp.js +228 -0
  127. package/dist/server/middleware-runtime.js +4 -3
  128. package/dist/server/middleware.d.ts +1 -1
  129. package/dist/server/middleware.js +2 -1
  130. package/dist/server/pages-api-route.d.ts +2 -0
  131. package/dist/server/pages-api-route.js +4 -1
  132. package/dist/server/pages-data-route.d.ts +11 -1
  133. package/dist/server/pages-data-route.js +16 -1
  134. package/dist/server/pages-dev-hydration.js +0 -1
  135. package/dist/server/pages-get-initial-props.d.ts +16 -3
  136. package/dist/server/pages-get-initial-props.js +17 -10
  137. package/dist/server/pages-i18n.js +64 -16
  138. package/dist/server/pages-node-compat.d.ts +2 -0
  139. package/dist/server/pages-node-compat.js +7 -3
  140. package/dist/server/pages-page-data.d.ts +64 -10
  141. package/dist/server/pages-page-data.js +349 -80
  142. package/dist/server/pages-page-handler.d.ts +9 -3
  143. package/dist/server/pages-page-handler.js +131 -36
  144. package/dist/server/pages-page-response.d.ts +5 -3
  145. package/dist/server/pages-page-response.js +24 -27
  146. package/dist/server/pages-readiness.d.ts +3 -3
  147. package/dist/server/pages-request-pipeline.d.ts +8 -0
  148. package/dist/server/pages-request-pipeline.js +30 -12
  149. package/dist/server/pages-revalidate.d.ts +1 -1
  150. package/dist/server/pages-revalidate.js +54 -8
  151. package/dist/server/pages-router-entry.d.ts +1 -0
  152. package/dist/server/pages-router-entry.js +16 -4
  153. package/dist/server/prerender-route-params.js +2 -2
  154. package/dist/server/prod-server.d.ts +3 -5
  155. package/dist/server/prod-server.js +72 -35
  156. package/dist/server/request-pipeline.d.ts +15 -29
  157. package/dist/server/request-pipeline.js +24 -59
  158. package/dist/server/revalidation-host.d.ts +11 -0
  159. package/dist/server/revalidation-host.js +19 -0
  160. package/dist/server/rsc-stream-hints.js +122 -18
  161. package/dist/server/worker-revalidation-context.d.ts +13 -0
  162. package/dist/server/worker-revalidation-context.js +29 -0
  163. package/dist/shims/app.d.ts +1 -1
  164. package/dist/shims/cache-handler.d.ts +1 -1
  165. package/dist/shims/cache-handler.js +10 -7
  166. package/dist/shims/cache-request-state.d.ts +27 -1
  167. package/dist/shims/cache-request-state.js +60 -1
  168. package/dist/shims/cache-runtime.d.ts +18 -1
  169. package/dist/shims/cache-runtime.js +26 -8
  170. package/dist/shims/cache.d.ts +5 -5
  171. package/dist/shims/cache.js +27 -11
  172. package/dist/shims/document.d.ts +42 -83
  173. package/dist/shims/document.js +62 -53
  174. package/dist/shims/dynamic.d.ts +5 -25
  175. package/dist/shims/dynamic.js +29 -8
  176. package/dist/shims/error.d.ts +1 -1
  177. package/dist/shims/error.js +2 -2
  178. package/dist/shims/fetch-cache.js +13 -4
  179. package/dist/shims/font-google-base.d.ts +11 -4
  180. package/dist/shims/font-google-base.js +17 -8
  181. package/dist/shims/font-local.d.ts +10 -3
  182. package/dist/shims/font-local.js +41 -10
  183. package/dist/shims/head.d.ts +13 -2
  184. package/dist/shims/head.js +3 -3
  185. package/dist/shims/headers.d.ts +37 -43
  186. package/dist/shims/headers.js +183 -74
  187. package/dist/shims/image.d.ts +27 -37
  188. package/dist/shims/image.js +21 -14
  189. package/dist/shims/internal/cookie-serialize.d.ts +12 -9
  190. package/dist/shims/internal/cookie-serialize.js +10 -7
  191. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  192. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  193. package/dist/shims/internal/interpolate-as.js +27 -2
  194. package/dist/shims/internal/utils.d.ts +3 -3
  195. package/dist/shims/legacy-image.d.ts +3 -37
  196. package/dist/shims/legacy-image.js +6 -16
  197. package/dist/shims/link.d.ts +15 -22
  198. package/dist/shims/link.js +34 -13
  199. package/dist/shims/metadata.d.ts +7 -17
  200. package/dist/shims/metadata.js +74 -24
  201. package/dist/shims/navigation-context-state.d.ts +1 -1
  202. package/dist/shims/navigation.d.ts +7 -3
  203. package/dist/shims/navigation.js +25 -14
  204. package/dist/shims/navigation.react-server.js +1 -1
  205. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  206. package/dist/shims/next-shims-public.d.ts +1 -0
  207. package/dist/shims/public-shim-map.json.js +103 -0
  208. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  209. package/dist/shims/readonly-url-search-params.js +3 -3
  210. package/dist/shims/request-context.d.ts +4 -1
  211. package/dist/shims/request-state-types.d.ts +1 -1
  212. package/dist/shims/router.d.ts +55 -21
  213. package/dist/shims/router.js +180 -44
  214. package/dist/shims/script.d.ts +6 -10
  215. package/dist/shims/script.js +7 -4
  216. package/dist/shims/server.d.ts +50 -26
  217. package/dist/shims/server.js +193 -55
  218. package/dist/shims/unified-request-context.d.ts +22 -3
  219. package/dist/shims/unified-request-context.js +84 -1
  220. package/dist/shims/url-safety.d.ts +1 -1
  221. package/dist/shims/url-safety.js +2 -2
  222. package/dist/typegen.d.ts +8 -2
  223. package/dist/typegen.js +76 -15
  224. package/dist/utils/cache-control-metadata.d.ts +2 -1
  225. package/dist/utils/cache-control-metadata.js +5 -1
  226. package/dist/utils/domain-locale.d.ts +2 -2
  227. package/dist/utils/external-url.d.ts +5 -0
  228. package/dist/utils/external-url.js +7 -0
  229. package/dist/utils/html-limited-bots.js +1 -1
  230. package/dist/utils/protocol-headers.d.ts +7 -1
  231. package/dist/utils/protocol-headers.js +7 -1
  232. package/dist/utils/regex-safety.d.ts +8 -0
  233. package/dist/utils/regex-safety.js +737 -0
  234. package/package.json +13 -2
@@ -4,7 +4,7 @@ import { VINEXT_RSC_MARKER_HEADER } from "../server/headers.js";
4
4
  import { getDataCacheHandler } from "./cache-handler.js";
5
5
  import { trackPprFallbackShellCacheTask } from "./ppr-fallback-shell.js";
6
6
  import { markDynamicUsage } from "./headers.js";
7
- import { _registerCacheContextAccessor, _setRequestScopedCacheLife, cacheLifeProfiles } from "./cache-request-state.js";
7
+ import { _hasPendingRevalidatedTag, _registerCacheContextAccessor, _setRequestScopedCacheLife, cacheLifeProfiles } from "./cache-request-state.js";
8
8
  import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.js";
9
9
  import { isMarkedAppPagePropsObject, markAppPagePropsForUseCache } from "./internal/app-page-props-cache-key.js";
10
10
  //#region src/shims/cache-runtime.ts
@@ -102,6 +102,16 @@ function getUseCacheBuildIdDefine() {
102
102
  function getUseCacheKeySeed() {
103
103
  return getUseCacheDeploymentIdDefine() || getUseCacheBuildIdDefine();
104
104
  }
105
+ /**
106
+ * Build the shared-cache key for a "use cache" function from its build-scoped
107
+ * identity and serialized arguments.
108
+ *
109
+ * This is a logical handler key, not a storage key. Backend-specific adapters
110
+ * are responsible for mapping it to their physical key constraints after
111
+ * applying any storage prefixes.
112
+ *
113
+ * Exported for testing.
114
+ */
105
115
  function buildUseCacheKey(id, keySeed, argsKey) {
106
116
  const scopedId = keySeed ? `build:${encodeURIComponent(keySeed)}:${id}` : id;
107
117
  return argsKey === void 0 ? `use-cache:${scopedId}` : `use-cache:${scopedId}:${argsKey}`;
@@ -263,11 +273,16 @@ function registerCachedFunction(fn, id, variant, options = {}) {
263
273
  if (isDev) return executeWithContext(fn, args, cacheVariant);
264
274
  const handler = getDataCacheHandler();
265
275
  const softTags = getCurrentFetchSoftTags();
266
- const existing = await handler.get(cacheKey, {
267
- kind: "FETCH",
268
- softTags
269
- });
270
- if (existing?.value && existing.value.kind === "FETCH" && existing.cacheState !== "stale") try {
276
+ let existing = null;
277
+ if (!_hasPendingRevalidatedTag(softTags)) try {
278
+ existing = await handler.get(cacheKey, {
279
+ kind: "FETCH",
280
+ softTags
281
+ });
282
+ } catch (error) {
283
+ console.error("[vinext] use cache: handler.get failed; treating as a cache miss:", error);
284
+ }
285
+ if (existing?.value && existing.value.kind === "FETCH" && existing.cacheState !== "stale" && !_hasPendingRevalidatedTag([...existing.value.tags ?? [], ...softTags])) try {
271
286
  propagateCacheTagsToRequest(existing.value.tags);
272
287
  if (rsc && existing.value.data.headers["x-vinext-rsc"] === "1") {
273
288
  const stream = uint8ToStream(base64ToUint8(existing.value.data.body));
@@ -319,10 +334,13 @@ function registerCachedFunction(fn, id, variant, options = {}) {
319
334
  configurable: true
320
335
  });
321
336
  cachedFn[USE_CACHE_FUNCTION_SYMBOL] = true;
337
+ if (options.acceptsSecondArgument !== void 0) Reflect.set(cachedFn, USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL, options.acceptsSecondArgument);
322
338
  return cachedFn;
323
339
  }
324
340
  /** @internal Symbol used to identify "use cache" wrapper functions. */
325
341
  const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
342
+ /** @internal Symbol carrying transform-derived cached function argument metadata. */
343
+ const USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL = Symbol.for("vinext.useCacheAcceptsSecondArgument");
326
344
  function throwPrivateUseCacheInsidePublicUseCacheError() {
327
345
  const error = /* @__PURE__ */ new Error("\"use cache: private\" must not be used within \"use cache\". It can only be nested inside of another \"use cache: private\".");
328
346
  const ctx = getRequestContext();
@@ -332,7 +350,7 @@ function throwPrivateUseCacheInsidePublicUseCacheError() {
332
350
  function recordRequestScopedCacheControl(cacheControl) {
333
351
  if (cacheControl === void 0) return;
334
352
  _setRequestScopedCacheLife({
335
- revalidate: cacheControl.revalidate,
353
+ revalidate: cacheControl.revalidate === false ? void 0 : cacheControl.revalidate,
336
354
  expire: cacheControl.expire
337
355
  });
338
356
  }
@@ -449,4 +467,4 @@ function stableStringify(value, seen) {
449
467
  return JSON.stringify(value);
450
468
  }
451
469
  //#endregion
452
- export { NestedDynamicUseCacheError, cacheContextStorage, clearPrivateCache, getCacheContext, markAppPagePropsForUseCache, registerCachedFunction, replyToCacheKey, runWithPrivateCache };
470
+ export { NestedDynamicUseCacheError, buildUseCacheKey, cacheContextStorage, clearPrivateCache, getCacheContext, markAppPagePropsForUseCache, registerCachedFunction, replyToCacheKey, runWithPrivateCache };
@@ -1,4 +1,4 @@
1
- import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
1
+ import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
2
2
  import { ExecutionContextLike, getRequestExecutionContext, runWithExecutionContext } from "./request-context.js";
3
3
  import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
4
4
 
@@ -18,7 +18,7 @@ import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerVa
18
18
  */
19
19
  declare function revalidateTag(tag: string, profile?: string | {
20
20
  expire?: number;
21
- }): Promise<void>;
21
+ }): undefined;
22
22
  /**
23
23
  * Revalidate cached data associated with a specific path.
24
24
  *
@@ -34,7 +34,7 @@ declare function revalidateTag(tag: string, profile?: string | {
34
34
  * The `type` parameter is App Router only — Pages Router does not generate
35
35
  * layout/page hierarchy tags, so only no-type invalidation applies there.
36
36
  */
37
- declare function revalidatePath(path: string, type?: "page" | "layout"): Promise<void>;
37
+ declare function revalidatePath(path: string, type?: "page" | "layout"): undefined;
38
38
  /**
39
39
  * No-op shim for API compatibility.
40
40
  *
@@ -57,7 +57,7 @@ declare function refresh(): void;
57
57
  *
58
58
  * @see https://nextjs.org/docs/app/api-reference/functions/updateTag
59
59
  */
60
- declare function updateTag(tag: string): Promise<void>;
60
+ declare function updateTag(tag: string): undefined;
61
61
  /**
62
62
  * Opt out of static rendering and indicate a particular component should not be cached.
63
63
  *
@@ -142,4 +142,4 @@ type UnstableCacheOptions = {
142
142
  */
143
143
  declare function unstable_cache<T extends (...args: any[]) => Promise<any>>(fn: T, keyParts?: string[], options?: UnstableCacheOptions): T;
144
144
  //#endregion
145
- export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
145
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
@@ -4,11 +4,11 @@ import { getRequestExecutionContext, runWithExecutionContext } from "./request-c
4
4
  import { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
5
5
  import { getCdnCacheAdapter } from "./cdn-cache.js";
6
6
  import { fnv1a64 } from "../utils/hash.js";
7
+ import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
7
8
  import { makeHangingPromise } from "./internal/make-hanging-promise.js";
8
9
  import { getHeadersAccessPhase, isDraftModeEnabled, markDynamicUsage } from "./headers.js";
9
- import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
10
- import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
11
- import { addCollectedRequestTags } from "./fetch-cache.js";
10
+ import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
11
+ import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.js";
12
12
  import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
13
13
  //#region src/shims/cache.ts
14
14
  /**
@@ -32,6 +32,14 @@ import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
32
32
  * target used by the generated cache-adapter module.
33
33
  */
34
34
  const _g = globalThis;
35
+ function scheduleRevalidation(promise) {
36
+ const executionContext = getRequestExecutionContext();
37
+ const queued = _queuePendingRevalidation(promise);
38
+ if (executionContext) executionContext.waitUntil(promise);
39
+ else if (!queued) promise.catch((error) => {
40
+ console.error("[vinext] cache revalidation failed:", error);
41
+ });
42
+ }
35
43
  /**
36
44
  * Revalidate cached data associated with a specific cache tag.
37
45
  *
@@ -45,14 +53,16 @@ const _g = globalThis;
45
53
  * @param tag - Cache tag to revalidate
46
54
  * @param profile - cacheLife profile name (e.g. 'max', 'hours') or inline { expire: number }
47
55
  */
48
- async function revalidateTag(tag, profile) {
56
+ function revalidateTag(tag, profile) {
49
57
  let durations;
50
58
  if (typeof profile === "string") {
51
59
  const resolved = cacheLifeProfiles[profile];
52
60
  if (resolved) durations = { expire: resolved.expire };
53
61
  } else if (profile && typeof profile === "object") durations = profile;
54
62
  if (!profile || !durations || durations.expire === 0) markActionRevalidation(1);
55
- await _invalidateEncodedTag(encodeCacheTag(tag), durations);
63
+ const encodedTag = encodeCacheTag(tag);
64
+ _markPendingRevalidatedTag(encodedTag);
65
+ return scheduleRevalidation(_invalidateEncodedTag(encodedTag, durations));
56
66
  }
57
67
  /**
58
68
  * Invalidate one already-encoded tag across both cache layers.
@@ -82,10 +92,12 @@ async function _invalidateEncodedTag(encoded, durations) {
82
92
  * The `type` parameter is App Router only — Pages Router does not generate
83
93
  * layout/page hierarchy tags, so only no-type invalidation applies there.
84
94
  */
85
- async function revalidatePath(path, type) {
95
+ function revalidatePath(path, type) {
86
96
  markActionRevalidation(1);
87
97
  const stem = path.endsWith("/") ? path.slice(0, -1) : path;
88
- await _invalidateEncodedTag(encodeCacheTag(type ? `_N_T_${stem}/${type}` : `_N_T_${stem || "/"}`));
98
+ const encodedTag = encodeCacheTag(type ? `_N_T_${stem}/${type}` : `_N_T_${stem || "/"}`);
99
+ _markPendingRevalidatedTag(encodedTag);
100
+ return scheduleRevalidation(_invalidateEncodedTag(encodedTag));
89
101
  }
90
102
  /**
91
103
  * No-op shim for API compatibility.
@@ -114,7 +126,9 @@ function refresh() {
114
126
  function updateTag(tag) {
115
127
  if (getHeadersAccessPhase() !== "action") throw new Error("updateTag can only be called from within a Server Action. To invalidate cache tags in Route Handlers or other contexts, use revalidateTag instead. See more info here: https://nextjs.org/docs/app/api-reference/functions/updateTag");
116
128
  markActionRevalidation(1);
117
- return _invalidateEncodedTag(encodeCacheTag(tag));
129
+ const encodedTag = encodeCacheTag(tag);
130
+ _markPendingRevalidatedTag(encodedTag);
131
+ return scheduleRevalidation(_invalidateEncodedTag(encodedTag));
118
132
  }
119
133
  /**
120
134
  * Opt out of static rendering and indicate a particular component should not be cached.
@@ -386,9 +400,11 @@ function unstable_cache(fn, keyParts, options) {
386
400
  });
387
401
  const isDraftMode = isDraftModeEnabled();
388
402
  if (!isDraftMode) {
389
- const existing = await getDataCacheHandler().get(cacheKey, {
403
+ const softTags = getCurrentFetchSoftTags();
404
+ const existing = _hasPendingRevalidatedTag([...tags, ...softTags]) ? null : await getDataCacheHandler().get(cacheKey, {
390
405
  kind: "FETCH",
391
- tags
406
+ tags,
407
+ softTags
392
408
  });
393
409
  if (existing?.value && existing.value.kind === "FETCH") {
394
410
  const cached = tryDeserializeUnstableCacheResult(existing.value.data.body);
@@ -406,4 +422,4 @@ function unstable_cache(fn, keyParts, options) {
406
422
  return cachedFn;
407
423
  }
408
424
  //#endregion
409
- export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
425
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
@@ -1,92 +1,51 @@
1
1
  import React from "react";
2
+ import { DocumentContext, DocumentInitialProps, DocumentProps } from "@vinext/types/next/upstream/dist/shared/lib/utils";
3
+ import { HtmlProps } from "@vinext/types/next/upstream/dist/shared/lib/html-context.shared-runtime";
2
4
 
3
5
  //#region src/shims/document.d.ts
4
- declare function Html({
5
- children,
6
- lang,
7
- ...props
8
- }: React.HTMLAttributes<HTMLHtmlElement> & {
6
+ type OriginProps = {
7
+ nonce?: string;
8
+ crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
9
9
  children?: React.ReactNode;
10
- }): React.JSX.Element;
11
- /**
12
- * Document Head - renders <head> with children.
13
- * The dev server injects meta tags, styles, etc.
14
- *
15
- * Note: charset and viewport are intentionally NOT hardcoded here. Those
16
- * defaults are seeded by `next/head`'s `defaultHead()` and emitted alongside
17
- * user `<Head>` tags via `getSSRHeadHTML()`, matching Next.js's canonical
18
- * ordering (`<meta charset>` first, then `<meta viewport>`, then user tags,
19
- * all with `data-next-head=""`). See `test/e2e/next-head/index.test.ts`.
20
- */
21
- declare function Head({
22
- children
23
- }: {
24
- children?: React.ReactNode;
25
- }): React.JSX.Element;
26
- /**
27
- * Main - renders the page content container.
28
- */
29
- declare function Main(): React.JSX.Element;
30
- /**
31
- * NextScript - renders a placeholder that the dev-server replaces with
32
- * actual hydration scripts (__NEXT_DATA__ + entry module).
33
- * Uses dangerouslySetInnerHTML so the HTML comment survives renderToString.
34
- */
35
- declare function NextScript(): React.JSX.Element;
36
- /**
37
- * Stand-ins for Next.js's `DocumentContext` / `DocumentInitialProps`.
38
- * The signatures match Next.js so custom `_document.tsx` subclasses can use
39
- * `ctx.renderPage()` enhancers and delegate through
40
- * `await Document.getInitialProps(ctx)` with the expected public types.
41
- *
42
- * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/utils.ts
43
- */
44
- type DocumentContext = {
45
- renderPage: (options?: {
46
- enhanceApp?: (App: React.ComponentType<{
47
- children?: React.ReactNode;
48
- }>) => React.ComponentType<{
49
- children?: React.ReactNode;
50
- }>;
51
- enhanceComponent?: (Comp: React.ComponentType<unknown>) => React.ComponentType<unknown>;
52
- } | ((Comp: React.ComponentType<unknown>) => React.ComponentType<unknown>)) => DocumentInitialProps | Promise<DocumentInitialProps>;
53
- defaultGetInitialProps: (ctx: DocumentContext, options?: {
54
- nonce?: string;
55
- }) => Promise<DocumentInitialProps>;
56
- pathname?: string;
57
- query?: Record<string, string | string[] | undefined>;
58
- asPath?: string;
59
- err?: any;
60
10
  };
61
- type DocumentInitialProps = {
62
- html: string;
63
- head?: ReadonlyArray<React.ReactElement>;
64
- styles?: React.ReactElement[] | Iterable<React.ReactNode> | React.ReactElement;
11
+ type DocumentFiles = {
12
+ sharedFiles: readonly string[];
13
+ pageFiles: readonly string[];
14
+ allFiles: readonly string[];
65
15
  };
66
- /**
67
- * Default Document component — also the base class user `_document.tsx` files
68
- * `extend`. Must be a class (not a function) to match Next.js's `next/document`
69
- * default export so `class MyDocument extends Document` produces a constructible
70
- * class that React can instantiate during SSR. Returning a function here breaks
71
- * any user `_document.tsx` that uses the class-based form because `extends`
72
- * against a non-constructor produces a class that can only be called without
73
- * `new`, which React refuses to do.
74
- *
75
- * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/pages/_document.tsx
76
- * Ported behavior: Next.js's default `Document` is a `class Document extends
77
- * React.Component`. Custom documents extend it and override `getInitialProps`
78
- * and `render`. Generic default matches Next.js (`P = {}`).
79
- */
80
- declare class Document<P = {}> extends React.Component<P & {
81
- children?: React.ReactNode;
82
- }> {
83
- /**
84
- * `getInitialProps` is invoked by the SSR pipeline. The runtime-provided
85
- * `ctx.defaultGetInitialProps()` owns the page render and style collection,
86
- * matching Next.js's canonical CSS-in-JS integration path.
87
- */
16
+ type HeadProps = OriginProps & React.ComponentPropsWithoutRef<"head">;
17
+ declare function Html(props: React.DetailedHTMLProps<React.HtmlHTMLAttributes<HTMLHtmlElement>, HTMLHtmlElement>): React.ReactElement;
18
+ interface Head {
19
+ context: HtmlProps;
20
+ }
21
+ declare class Head extends React.Component<HeadProps> {
22
+ static contextType: React.Context<HtmlProps | undefined>;
23
+ getCssLinks(_files: DocumentFiles): React.ReactElement[] | null;
24
+ getPreloadDynamicChunks(): Array<React.ReactElement | null>;
25
+ getPreloadMainLinks(_files: DocumentFiles): React.ReactElement[] | null;
26
+ getBeforeInteractiveInlineScripts(): React.ReactElement[];
27
+ getDynamicChunks(_files: DocumentFiles): Array<React.ReactElement | null>;
28
+ getPreNextScripts(): React.ReactElement;
29
+ getScripts(_files: DocumentFiles): React.ReactElement[];
30
+ getPolyfillScripts(): React.ReactElement[];
31
+ render(): React.ReactElement;
32
+ }
33
+ declare function Main(): React.ReactElement;
34
+ interface NextScript {
35
+ context: HtmlProps;
36
+ }
37
+ declare class NextScript extends React.Component<OriginProps> {
38
+ static contextType: React.Context<HtmlProps | undefined>;
39
+ getDynamicChunks(_files: DocumentFiles): Array<React.ReactElement | null>;
40
+ getPreNextScripts(): React.ReactElement;
41
+ getScripts(_files: DocumentFiles): React.ReactElement[];
42
+ getPolyfillScripts(): React.ReactElement[];
43
+ static getInlineScriptSource(context: Readonly<HtmlProps>): string;
44
+ render(): React.ReactElement;
45
+ }
46
+ declare class Document<P = {}> extends React.Component<DocumentProps & P> {
88
47
  static getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps>;
89
- render(): React.ReactNode;
48
+ render(): React.ReactElement;
90
49
  }
91
50
  //#endregion
92
- export { DocumentContext, DocumentInitialProps, Head, Html, Main, NextScript, Document as default };
51
+ export { type DocumentContext, type DocumentInitialProps, type DocumentProps, Head, Html, Main, NextScript, OriginProps, Document as default };
@@ -1,70 +1,79 @@
1
1
  import React from "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/shims/document.tsx
4
4
  /**
5
5
  * next/document shim
6
6
  *
7
- * Provides Html, Head, Main, NextScript components for custom _document.tsx.
8
- * During SSR these render placeholder markers that the dev server replaces
9
- * with actual content.
7
+ * Provides Html, Head, Main, NextScript, and the class-based Document API for
8
+ * custom Pages Router documents. Vinext's renderer replaces the Main and
9
+ * NextScript placeholders with the rendered page and hydration scripts.
10
10
  */
11
- function Html({ children, lang, ...props }) {
12
- return /* @__PURE__ */ jsx("html", {
13
- lang,
14
- ...props,
15
- children
16
- });
17
- }
18
- /**
19
- * Document Head - renders <head> with children.
20
- * The dev server injects meta tags, styles, etc.
21
- *
22
- * Note: charset and viewport are intentionally NOT hardcoded here. Those
23
- * defaults are seeded by `next/head`'s `defaultHead()` and emitted alongside
24
- * user `<Head>` tags via `getSSRHeadHTML()`, matching Next.js's canonical
25
- * ordering (`<meta charset>` first, then `<meta viewport>`, then user tags,
26
- * all with `data-next-head=""`). See `test/e2e/next-head/index.test.ts`.
27
- */
28
- function Head({ children }) {
29
- return /* @__PURE__ */ jsx("head", { children });
11
+ const HtmlContext = React.createContext(void 0);
12
+ function Html(props) {
13
+ return /* @__PURE__ */ jsx("html", { ...props });
30
14
  }
31
- /**
32
- * Main - renders the page content container.
33
- */
15
+ var Head = class extends React.Component {
16
+ static contextType = HtmlContext;
17
+ getCssLinks(_files) {
18
+ return null;
19
+ }
20
+ getPreloadDynamicChunks() {
21
+ return [];
22
+ }
23
+ getPreloadMainLinks(_files) {
24
+ return null;
25
+ }
26
+ getBeforeInteractiveInlineScripts() {
27
+ return [];
28
+ }
29
+ getDynamicChunks(_files) {
30
+ return [];
31
+ }
32
+ getPreNextScripts() {
33
+ return /* @__PURE__ */ jsx(Fragment$1, {});
34
+ }
35
+ getScripts(_files) {
36
+ return [];
37
+ }
38
+ getPolyfillScripts() {
39
+ return [];
40
+ }
41
+ render() {
42
+ const { children, ...props } = this.props;
43
+ return /* @__PURE__ */ jsx("head", {
44
+ ...props,
45
+ children
46
+ });
47
+ }
48
+ };
34
49
  function Main() {
35
50
  return /* @__PURE__ */ jsx("div", {
36
51
  id: "__next",
37
52
  dangerouslySetInnerHTML: { __html: "__NEXT_MAIN__" }
38
53
  });
39
54
  }
40
- /**
41
- * NextScript - renders a placeholder that the dev-server replaces with
42
- * actual hydration scripts (__NEXT_DATA__ + entry module).
43
- * Uses dangerouslySetInnerHTML so the HTML comment survives renderToString.
44
- */
45
- function NextScript() {
46
- return /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: "<!-- __NEXT_SCRIPTS__ -->" } });
47
- }
48
- /**
49
- * Default Document component — also the base class user `_document.tsx` files
50
- * `extend`. Must be a class (not a function) to match Next.js's `next/document`
51
- * default export so `class MyDocument extends Document` produces a constructible
52
- * class that React can instantiate during SSR. Returning a function here breaks
53
- * any user `_document.tsx` that uses the class-based form because `extends`
54
- * against a non-constructor produces a class that can only be called without
55
- * `new`, which React refuses to do.
56
- *
57
- * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/pages/_document.tsx
58
- * Ported behavior: Next.js's default `Document` is a `class Document extends
59
- * React.Component`. Custom documents extend it and override `getInitialProps`
60
- * and `render`. Generic default matches Next.js (`P = {}`).
61
- */
55
+ var NextScript = class extends React.Component {
56
+ static contextType = HtmlContext;
57
+ getDynamicChunks(_files) {
58
+ return [];
59
+ }
60
+ getPreNextScripts() {
61
+ return /* @__PURE__ */ jsx(Fragment$1, {});
62
+ }
63
+ getScripts(_files) {
64
+ return [];
65
+ }
66
+ getPolyfillScripts() {
67
+ return [];
68
+ }
69
+ static getInlineScriptSource(context) {
70
+ return JSON.stringify(context.__NEXT_DATA__);
71
+ }
72
+ render() {
73
+ return /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: "<!-- __NEXT_SCRIPTS__ -->" } });
74
+ }
75
+ };
62
76
  var Document = class extends React.Component {
63
- /**
64
- * `getInitialProps` is invoked by the SSR pipeline. The runtime-provided
65
- * `ctx.defaultGetInitialProps()` owns the page render and style collection,
66
- * matching Next.js's canonical CSS-in-JS integration path.
67
- */
68
77
  static getInitialProps(ctx) {
69
78
  return ctx.defaultGetInitialProps(ctx);
70
79
  }
@@ -1,28 +1,7 @@
1
- import { ComponentType } from "react";
1
+ import React, { ComponentType } from "react";
2
+ import { DynamicOptions, DynamicOptionsLoadingProps, LoadableComponent, LoadableFn, LoadableGeneratedOptions, LoadableOptions, Loader, LoaderComponent, LoaderMap } from "@vinext/types/next/upstream/dynamic";
2
3
 
3
4
  //#region src/shims/dynamic.d.ts
4
- type DynamicLoadingProps = {
5
- error?: Error | null;
6
- isLoading?: boolean;
7
- pastDelay?: boolean;
8
- retry?: () => void;
9
- timedOut?: boolean;
10
- };
11
- type ComponentModule<P> = {
12
- default: ComponentType<P>;
13
- };
14
- type LoaderComponent<P> = Promise<ComponentModule<P> | ComponentType<P>>;
15
- type LoaderFn<P> = () => LoaderComponent<P>;
16
- type DynamicOptions<P> = {
17
- loading?: ComponentType<DynamicLoadingProps>;
18
- loader?: Loader<P>;
19
- loadableGenerated?: {
20
- modules?: readonly string[];
21
- };
22
- modules?: readonly string[];
23
- ssr?: boolean;
24
- };
25
- type Loader<P> = LoaderFn<P> | LoaderComponent<P>;
26
5
  type DynamicInput<P> = DynamicOptions<P> | Loader<P>;
27
6
  /**
28
7
  * Wait for all pending dynamic() preloads to resolve, then clear the queue.
@@ -30,6 +9,7 @@ type DynamicInput<P> = DynamicOptions<P> | Loader<P>;
30
9
  * No-op for the App Router path which uses React.lazy + Suspense.
31
10
  */
32
11
  declare function flushPreloads(): Promise<void[]>;
33
- declare function dynamic<P extends object = object>(dynamicInput: DynamicInput<P>, options?: DynamicOptions<P>): ComponentType<P>;
12
+ declare function dynamic<P = {}>(dynamicInput: DynamicInput<P>, options?: DynamicOptions<P>): ComponentType<P>;
13
+ declare function noSSR<P = {}>(LoadableInitializer: LoadableFn<P>, loadableOptions: DynamicOptions<P>): React.ComponentType<P>;
34
14
  //#endregion
35
- export { dynamic as default, flushPreloads };
15
+ export { type DynamicOptions, type DynamicOptionsLoadingProps, type LoadableComponent, type LoadableFn, type LoadableGeneratedOptions, type LoadableOptions, type Loader, type LoaderComponent, type LoaderMap, dynamic as default, flushPreloads, noSSR };
@@ -68,6 +68,9 @@ function useRetryableLazyComponent(loader, initialLazyComponent) {
68
68
  retryKey
69
69
  };
70
70
  }
71
+ function createElementWithProps(Component, props) {
72
+ return React.createElement(Component, props);
73
+ }
71
74
  /**
72
75
  * Lightweight error boundary that renders the loading component with the error
73
76
  * when a dynamic() loader rejects. Without this, loader failures would propagate
@@ -122,9 +125,14 @@ function flushPreloads() {
122
125
  return Promise.all(pending);
123
126
  }
124
127
  function dynamic(dynamicInput, options) {
125
- const { loader: dynamicLoader, loadableGenerated, loading: LoadingComponent, modules, ssr = true } = normalizeDynamicOptions(dynamicInput, options);
128
+ const normalizedOptions = normalizeDynamicOptions(dynamicInput, options);
129
+ const { loader: dynamicLoader, loadableGenerated, loading: LoadingComponent, ssr = true } = normalizedOptions;
130
+ if (dynamicLoader && typeof dynamicLoader === "object" && !(dynamicLoader instanceof Promise)) throw new Error("next/dynamic loader maps are not supported by vinext");
126
131
  const loader = dynamicLoader ? normalizeLoader(dynamicLoader) : () => Promise.resolve(() => null);
127
- const preloadModuleIds = loadableGenerated?.modules ?? modules;
132
+ const generatedModules = loadableGenerated?.modules;
133
+ const optionModules = normalizedOptions.modules;
134
+ const configuredModules = generatedModules ?? optionModules;
135
+ const preloadModuleIds = typeof configuredModules === "function" ? Object.keys(configuredModules()) : configuredModules;
128
136
  if (!ssr) {
129
137
  if (isServer) {
130
138
  const SSRFalse = (_props) => LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps()) : null;
@@ -138,7 +146,7 @@ function dynamic(dynamicInput, options) {
138
146
  React.useEffect(() => setMounted(true), []);
139
147
  if (!mounted) return LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
140
148
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
141
- const lazyElement = React.createElement(LazyComponent, props);
149
+ const lazyElement = createElementWithProps(LazyComponent, props);
142
150
  let content = lazyElement;
143
151
  if (LoadingComponent) {
144
152
  const ErrorBoundary = getDynamicErrorBoundary();
@@ -157,8 +165,7 @@ function dynamic(dynamicInput, options) {
157
165
  if (typeof React.lazy !== "function") {
158
166
  const AsyncServerDynamic = async (props) => {
159
167
  const mod = await loader();
160
- const Component = "default" in mod ? mod.default : mod;
161
- return React.createElement(Component, props);
168
+ return createElementWithProps("default" in mod ? mod.default : mod, props);
162
169
  };
163
170
  AsyncServerDynamic.displayName = "DynamicAsyncServer";
164
171
  return AsyncServerDynamic;
@@ -166,7 +173,7 @@ function dynamic(dynamicInput, options) {
166
173
  const LazyServer = createLazyComponent(loader);
167
174
  const ServerDynamic = (props) => {
168
175
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps()) : null;
169
- const lazyElement = React.createElement(LazyServer, props);
176
+ const lazyElement = createElementWithProps(LazyServer, props);
170
177
  let content = lazyElement;
171
178
  if (LoadingComponent) {
172
179
  const ErrorBoundary = getDynamicErrorBoundary();
@@ -185,7 +192,7 @@ function dynamic(dynamicInput, options) {
185
192
  const ClientDynamic = (props) => {
186
193
  const { LazyComponent, retry, retryKey } = useRetryableLazyComponent(loader, InitialLazyComponent);
187
194
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
188
- const lazyElement = React.createElement(LazyComponent, props);
195
+ const lazyElement = createElementWithProps(LazyComponent, props);
189
196
  let content = lazyElement;
190
197
  if (LoadingComponent) {
191
198
  const ErrorBoundary = getDynamicErrorBoundary();
@@ -200,5 +207,19 @@ function dynamic(dynamicInput, options) {
200
207
  ClientDynamic.displayName = "DynamicClient";
201
208
  return ClientDynamic;
202
209
  }
210
+ function noSSR(LoadableInitializer, loadableOptions) {
211
+ delete loadableOptions.webpack;
212
+ delete loadableOptions.modules;
213
+ if (!isServer) return LoadableInitializer(loadableOptions);
214
+ const Loading = loadableOptions.loading;
215
+ const NoSSR = () => React.createElement(Loading, {
216
+ error: null,
217
+ isLoading: true,
218
+ pastDelay: false,
219
+ timedOut: false
220
+ });
221
+ NoSSR.displayName = "NoSSR";
222
+ return NoSSR;
223
+ }
203
224
  //#endregion
204
- export { dynamic as default, flushPreloads };
225
+ export { dynamic as default, flushPreloads, noSSR };
@@ -27,7 +27,7 @@ declare class ErrorComponent<P = {}> extends React.Component<P & ErrorProps> {
27
27
  render(): React.ReactElement;
28
28
  }
29
29
  type ErrorInfo = {
30
- error: unknown;
30
+ error: Error;
31
31
  reset: () => void;
32
32
  unstable_retry: () => void;
33
33
  };
@@ -1,8 +1,8 @@
1
1
  import { AppRouterContext } from "./internal/app-router-context.js";
2
2
  import { RouterContext } from "./internal/router-context.js";
3
- import Head from "./head.js";
4
3
  import { isNextRouterError } from "./navigation-errors.js";
5
4
  import "./navigation.js";
5
+ import Head from "./head.js";
6
6
  import { useUntrackedPathname } from "./internal/navigation-untracked.js";
7
7
  import React from "react";
8
8
  //#region src/shims/error.tsx
@@ -119,7 +119,7 @@ var _CatchError = class extends React.Component {
119
119
  if (this.state.error) {
120
120
  const Fallback = this.props.fallback;
121
121
  const errorInfo = {
122
- error: this.state.error.thrownValue,
122
+ error: this.state.error.thrownValue instanceof Error ? this.state.error.thrownValue : new Error(String(this.state.error.thrownValue)),
123
123
  reset: this.reset,
124
124
  unstable_retry: this.unstable_retry
125
125
  };