@wular/pnext 0.0.1

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 (371) hide show
  1. package/README.md +153 -0
  2. package/bin/pnext +67 -0
  3. package/config/lint/base.js +48 -0
  4. package/config/ts/base.json +26 -0
  5. package/config/ts/react.json +13 -0
  6. package/package.json +70 -0
  7. package/reference/compat.md +63 -0
  8. package/reference/config.md +120 -0
  9. package/reference/css.md +58 -0
  10. package/reference/dev.md +69 -0
  11. package/reference/env.md +40 -0
  12. package/reference/metadata.md +86 -0
  13. package/reference/navigation.md +149 -0
  14. package/reference/overview.md +35 -0
  15. package/reference/performance.md +97 -0
  16. package/reference/rendering.md +127 -0
  17. package/reference/routing.md +167 -0
  18. package/reference/typegen.md +64 -0
  19. package/src/api/cache.ts +80 -0
  20. package/src/api/client-cache.ts +9 -0
  21. package/src/api/client-navigation.ts +279 -0
  22. package/src/api/dynamic.tsx +102 -0
  23. package/src/api/link.tsx +119 -0
  24. package/src/api/navigation.ts +198 -0
  25. package/src/api/router/events.ts +53 -0
  26. package/src/api/router/history.ts +70 -0
  27. package/src/api/router/hub.ts +194 -0
  28. package/src/api/router/policies.ts +107 -0
  29. package/src/api/router/runtime.ts +5238 -0
  30. package/src/api/router/types.ts +299 -0
  31. package/src/api/router.ts +167 -0
  32. package/src/api/server.ts +323 -0
  33. package/src/api/suspense.ts +16 -0
  34. package/src/cache/context.ts +61 -0
  35. package/src/cli/adapters/vercel-warm.ts +375 -0
  36. package/src/cli/adapters/vercel.ts +1310 -0
  37. package/src/cli/analyze-print.ts +181 -0
  38. package/src/cli/analyze.ts +328 -0
  39. package/src/cli/boot-trace.ts +29 -0
  40. package/src/cli/build.ts +3114 -0
  41. package/src/cli/dev.ts +276 -0
  42. package/src/cli/index.ts +196 -0
  43. package/src/cli/named-bin.ts +119 -0
  44. package/src/cli/serve-ui.ts +160 -0
  45. package/src/cli/start.ts +1425 -0
  46. package/src/client/build.ts +2136 -0
  47. package/src/client/chunk-fold.ts +526 -0
  48. package/src/client/entry.ts +1525 -0
  49. package/src/client/paths.ts +22 -0
  50. package/src/client/prebuilt.ts +621 -0
  51. package/src/client/profile.ts +75 -0
  52. package/src/client/react-compiler.ts +94 -0
  53. package/src/client/reference-stub.ts +145 -0
  54. package/src/client/reference.ts +47 -0
  55. package/src/compat/actions/action-client.ts +531 -0
  56. package/src/compat/actions/action-dispatch.ts +676 -0
  57. package/src/compat/actions/action-router.ts +40 -0
  58. package/src/compat/actions/action-shared.ts +95 -0
  59. package/src/compat/actions/client-plugin.ts +135 -0
  60. package/src/compat/actions/client-stub.ts +65 -0
  61. package/src/compat/actions/config.ts +164 -0
  62. package/src/compat/actions/detect.ts +208 -0
  63. package/src/compat/actions/discovery.ts +244 -0
  64. package/src/compat/actions/early-submit.ts +40 -0
  65. package/src/compat/actions/endpoint.ts +602 -0
  66. package/src/compat/actions/flight.ts +52 -0
  67. package/src/compat/actions/form-state.ts +73 -0
  68. package/src/compat/actions/hoist.ts +485 -0
  69. package/src/compat/actions/ids.ts +39 -0
  70. package/src/compat/actions/index.ts +41 -0
  71. package/src/compat/actions/instances.ts +144 -0
  72. package/src/compat/actions/origin.ts +109 -0
  73. package/src/compat/actions/protocol.ts +125 -0
  74. package/src/compat/actions/registry.ts +74 -0
  75. package/src/compat/actions/rewrite.ts +282 -0
  76. package/src/compat/actions/serve.ts +414 -0
  77. package/src/compat/actions/server-tag.ts +21 -0
  78. package/src/compat/actions/unrecognized-error.ts +30 -0
  79. package/src/compat/adapter/build-complete.ts +257 -0
  80. package/src/compat/bundler/bun-externals.ts +53 -0
  81. package/src/compat/bundler/cjs-exports.ts +542 -0
  82. package/src/compat/bundler/config.ts +363 -0
  83. package/src/compat/bundler/externals.ts +34 -0
  84. package/src/compat/bundler/import-meta-url.ts +60 -0
  85. package/src/compat/bundler/modularize-imports.ts +119 -0
  86. package/src/compat/bundler/new-url-asset.ts +87 -0
  87. package/src/compat/bundler/optimize-package-imports.ts +273 -0
  88. package/src/compat/bundler/polyfill.ts +88 -0
  89. package/src/compat/bundler/react-compiler.ts +61 -0
  90. package/src/compat/bundler/react-profiler.tsx +25 -0
  91. package/src/compat/bundler/relay-transform.ts +116 -0
  92. package/src/compat/bundler/require-context.ts +281 -0
  93. package/src/compat/bundler/resolve-extensions.ts +75 -0
  94. package/src/compat/bundler/source-cache.ts +61 -0
  95. package/src/compat/bundler/static-imports.ts +25 -0
  96. package/src/compat/bundler/symlink-imports.ts +119 -0
  97. package/src/compat/bundler/tsconfig-paths.ts +50 -0
  98. package/src/compat/bundler/wasm.ts +153 -0
  99. package/src/compat/bundler/webpack-loaders.ts +685 -0
  100. package/src/compat/bundler/worker.ts +278 -0
  101. package/src/compat/cache/build-flags.ts +81 -0
  102. package/src/compat/cache/build-prerender-errors.ts +163 -0
  103. package/src/compat/cache/custom-handler.ts +159 -0
  104. package/src/compat/cache/fetch-patch.ts +745 -0
  105. package/src/compat/cache/handler.ts +100 -0
  106. package/src/compat/cache/modern-handler.ts +275 -0
  107. package/src/compat/cache/resume-data-cache.ts +143 -0
  108. package/src/compat/cache/revalidate.ts +759 -0
  109. package/src/compat/cache/runtime-error.ts +124 -0
  110. package/src/compat/cache/use-cache-transform.ts +961 -0
  111. package/src/compat/cache/use-cache.ts +1695 -0
  112. package/src/compat/cache-control.ts +269 -0
  113. package/src/compat/client/base-path.ts +64 -0
  114. package/src/compat/client/css-order.ts +36 -0
  115. package/src/compat/client/errors/control-flow.ts +92 -0
  116. package/src/compat/client/errors/error-boundary.ts +222 -0
  117. package/src/compat/client/errors/global-error.ts +238 -0
  118. package/src/compat/client/errors/install.ts +217 -0
  119. package/src/compat/client/errors/lazy.ts +53 -0
  120. package/src/compat/client/errors/primitive-throw.ts +126 -0
  121. package/src/compat/client/errors/soft-refresh.ts +14 -0
  122. package/src/compat/client/link-status.ts +86 -0
  123. package/src/compat/client/nav-compat-runtime.ts +57 -0
  124. package/src/compat/client/nav-compat.ts +42 -0
  125. package/src/compat/client/navigation-scroll.ts +154 -0
  126. package/src/compat/client/optimistic-routing.ts +206 -0
  127. package/src/compat/client/prefetch-cache.ts +111 -0
  128. package/src/compat/client/route-announcer.ts +72 -0
  129. package/src/compat/client/segment-cache-policy.ts +159 -0
  130. package/src/compat/client/segment-cache.ts +1077 -0
  131. package/src/compat/client/segment-prefetch.ts +375 -0
  132. package/src/compat/client/trailing-slash.ts +24 -0
  133. package/src/compat/css/chunking.ts +254 -0
  134. package/src/compat/css/inline-css.ts +73 -0
  135. package/src/compat/css/lightningcss.ts +90 -0
  136. package/src/compat/css/modules.ts +373 -0
  137. package/src/compat/css/nonce.ts +30 -0
  138. package/src/compat/css/sass-plugin.ts +65 -0
  139. package/src/compat/css/sass.ts +392 -0
  140. package/src/compat/css/styled-jsx-runtime.ts +80 -0
  141. package/src/compat/css/styled-jsx.ts +49 -0
  142. package/src/compat/edge-runtime.ts +71 -0
  143. package/src/compat/export/client.ts +112 -0
  144. package/src/compat/export/index.ts +272 -0
  145. package/src/compat/export/standalone.ts +207 -0
  146. package/src/compat/image-optimizer/cache.ts +119 -0
  147. package/src/compat/image-optimizer/detect.ts +143 -0
  148. package/src/compat/image-optimizer/index.ts +601 -0
  149. package/src/compat/image-optimizer/source.ts +243 -0
  150. package/src/compat/index.ts +458 -0
  151. package/src/compat/lifecycle/after-scope.ts +86 -0
  152. package/src/compat/lifecycle/after.ts +173 -0
  153. package/src/compat/lifecycle/error-funnel.ts +306 -0
  154. package/src/compat/lifecycle/error-serialize.ts +87 -0
  155. package/src/compat/lifecycle/error-ui.ts +167 -0
  156. package/src/compat/lifecycle/instrumentation-client.ts +138 -0
  157. package/src/compat/lifecycle/instrumentation.ts +277 -0
  158. package/src/compat/lifecycle/node-console.ts +19 -0
  159. package/src/compat/lifecycle/testmode.ts +263 -0
  160. package/src/compat/mdx/compile.ts +219 -0
  161. package/src/compat/mdx/next-mdx-stub.ts +46 -0
  162. package/src/compat/mdx/plugin.ts +37 -0
  163. package/src/compat/metadata-route-artifacts.ts +458 -0
  164. package/src/compat/metadata.ts +295 -0
  165. package/src/compat/middleware/manifest.ts +210 -0
  166. package/src/compat/misc/action-return.ts +173 -0
  167. package/src/compat/next/cache.ts +211 -0
  168. package/src/compat/next/canonical-url.ts +35 -0
  169. package/src/compat/next/client-cache.ts +57 -0
  170. package/src/compat/next/client-navigation.ts +313 -0
  171. package/src/compat/next/client-only.ts +3 -0
  172. package/src/compat/next/client-script.tsx +215 -0
  173. package/src/compat/next/client-server.ts +39 -0
  174. package/src/compat/next/config-loader.ts +569 -0
  175. package/src/compat/next/config.ts +29 -0
  176. package/src/compat/next/constants.cjs +6 -0
  177. package/src/compat/next/constants.ts +6 -0
  178. package/src/compat/next/custom-server.ts +236 -0
  179. package/src/compat/next/dist/client/components/app-router-headers.ts +32 -0
  180. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +38 -0
  181. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -0
  182. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -0
  183. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -0
  184. package/src/compat/next/dynamic.tsx +46 -0
  185. package/src/compat/next/error.tsx +148 -0
  186. package/src/compat/next/font/cache.ts +171 -0
  187. package/src/compat/next/font/google.ts +2 -0
  188. package/src/compat/next/font/index.ts +8 -0
  189. package/src/compat/next/font/local.ts +5 -0
  190. package/src/compat/next/font/runtime-client.ts +71 -0
  191. package/src/compat/next/font/runtime.ts +974 -0
  192. package/src/compat/next/font/shared.ts +281 -0
  193. package/src/compat/next/form.tsx +156 -0
  194. package/src/compat/next/head.tsx +10 -0
  195. package/src/compat/next/headers.ts +247 -0
  196. package/src/compat/next/image/config.ts +196 -0
  197. package/src/compat/next/image/optimizer.ts +96 -0
  198. package/src/compat/next/image/patterns.ts +103 -0
  199. package/src/compat/next/image/shared.ts +141 -0
  200. package/src/compat/next/image/static-metadata.ts +283 -0
  201. package/src/compat/next/image/validate.ts +269 -0
  202. package/src/compat/next/image-client.tsx +215 -0
  203. package/src/compat/next/image-props.ts +575 -0
  204. package/src/compat/next/image-usage.ts +102 -0
  205. package/src/compat/next/image.tsx +56 -0
  206. package/src/compat/next/index.ts +1 -0
  207. package/src/compat/next/legacy-image.tsx +97 -0
  208. package/src/compat/next/link-usage.ts +29 -0
  209. package/src/compat/next/link-validation-transform.ts +200 -0
  210. package/src/compat/next/link.tsx +466 -0
  211. package/src/compat/next/navigation.cjs +21 -0
  212. package/src/compat/next/navigation.ts +188 -0
  213. package/src/compat/next/offline.ts +51 -0
  214. package/src/compat/next/og.ts +324 -0
  215. package/src/compat/next/optimistic-route-state.ts +188 -0
  216. package/src/compat/next/preferred-region.ts +39 -0
  217. package/src/compat/next/redirects.ts +131 -0
  218. package/src/compat/next/resource-hints.ts +136 -0
  219. package/src/compat/next/rewrites.ts +350 -0
  220. package/src/compat/next/root-params.ts +142 -0
  221. package/src/compat/next/router.cjs +49 -0
  222. package/src/compat/next/router.ts +143 -0
  223. package/src/compat/next/script.tsx +355 -0
  224. package/src/compat/next/server-only.ts +3 -0
  225. package/src/compat/next/server.ts +28 -0
  226. package/src/compat/next/svgr.ts +58 -0
  227. package/src/compat/next/telemetry.ts +77 -0
  228. package/src/compat/next/user-agent.ts +100 -0
  229. package/src/compat/next/web-vitals.ts +56 -0
  230. package/src/compat/otel/api.ts +95 -0
  231. package/src/compat/otel/client-trace-metadata.ts +71 -0
  232. package/src/compat/otel/fetch-span.ts +77 -0
  233. package/src/compat/otel/tracer.ts +944 -0
  234. package/src/compat/pages/client-plugin.ts +108 -0
  235. package/src/compat/pages/index.ts +527 -0
  236. package/src/compat/pages/router-state.ts +94 -0
  237. package/src/compat/ppr/io.ts +38 -0
  238. package/src/compat/ppr/missing-root-params.ts +105 -0
  239. package/src/compat/ppr/root-params-scan.ts +164 -0
  240. package/src/compat/ppr/root-params-transform.ts +75 -0
  241. package/src/compat/ppr/root-params.ts +129 -0
  242. package/src/compat/ppr/segment-config-incompat.ts +34 -0
  243. package/src/compat/protocol.ts +202 -0
  244. package/src/compat/react/client.ts +59 -0
  245. package/src/compat/react/compiler-runtime.ts +60 -0
  246. package/src/compat/react/dom-client.ts +115 -0
  247. package/src/compat/react/dom-react-server.ts +20 -0
  248. package/src/compat/react/dom-server.ts +40 -0
  249. package/src/compat/react/dom.ts +154 -0
  250. package/src/compat/react/preact.ts +522 -0
  251. package/src/compat/react/react-server.ts +84 -0
  252. package/src/compat/react/router-shim.ts +26 -0
  253. package/src/compat/react/server-component-use.ts +48 -0
  254. package/src/compat/react/server-inserted-html.ts +87 -0
  255. package/src/compat/react/server.ts +156 -0
  256. package/src/compat/react/view-transition.ts +60 -0
  257. package/src/compat/register/actions.ts +875 -0
  258. package/src/compat/register/boot.ts +141 -0
  259. package/src/compat/register/build-tier.ts +11 -0
  260. package/src/compat/register/build.ts +182 -0
  261. package/src/compat/register/bundler.ts +587 -0
  262. package/src/compat/register/cache.ts +85 -0
  263. package/src/compat/register/client-errors.ts +18 -0
  264. package/src/compat/register/config.ts +17 -0
  265. package/src/compat/register/css-extras.ts +120 -0
  266. package/src/compat/register/edge-runtime.ts +6 -0
  267. package/src/compat/register/errors.ts +46 -0
  268. package/src/compat/register/export.ts +23 -0
  269. package/src/compat/register/font.ts +36 -0
  270. package/src/compat/register/hooks.ts +34 -0
  271. package/src/compat/register/image.ts +133 -0
  272. package/src/compat/register/index.ts +111 -0
  273. package/src/compat/register/instrumentation-client.ts +35 -0
  274. package/src/compat/register/lifecycle.ts +86 -0
  275. package/src/compat/register/mdx.ts +48 -0
  276. package/src/compat/register/middleware.ts +36 -0
  277. package/src/compat/register/misc.ts +44 -0
  278. package/src/compat/register/otel.ts +288 -0
  279. package/src/compat/register/pages-api.ts +473 -0
  280. package/src/compat/register/ppr.ts +56 -0
  281. package/src/compat/register/protocol.ts +57 -0
  282. package/src/compat/register/proxy.ts +127 -0
  283. package/src/compat/register/render.ts +268 -0
  284. package/src/compat/register/routing.ts +410 -0
  285. package/src/compat/register/segment.ts +1903 -0
  286. package/src/compat/register/static-image.ts +21 -0
  287. package/src/compat/register/typed-routes.ts +35 -0
  288. package/src/compat/register/usecache.ts +131 -0
  289. package/src/compat/register/validation.ts +56 -0
  290. package/src/compat/segment/loading-boundary.ts +113 -0
  291. package/src/compat/segment/page-slot.ts +200 -0
  292. package/src/compat/segment/tree.ts +481 -0
  293. package/src/compat/segment/vary-key.ts +102 -0
  294. package/src/compat/segment/vary-params.ts +551 -0
  295. package/src/compat/static-params.ts +33 -0
  296. package/src/compat/tsconfig-defaults.ts +301 -0
  297. package/src/compat/typecheck/index.ts +1481 -0
  298. package/src/compat/typecheck/worker.ts +26 -0
  299. package/src/compat/typed-routes/index.ts +92 -0
  300. package/src/compat/typed-routes/manifest.ts +356 -0
  301. package/src/compat/typed-routes/typegen.ts +566 -0
  302. package/src/compat/validation/errors.ts +159 -0
  303. package/src/compat/validation/index.ts +1770 -0
  304. package/src/compat/validation/prerender-diagnostics.ts +1508 -0
  305. package/src/compat-bootstrap.ts +67 -0
  306. package/src/config.ts +218 -0
  307. package/src/css/build.ts +697 -0
  308. package/src/css/index.ts +2 -0
  309. package/src/css/postcss.ts +236 -0
  310. package/src/css/worker.ts +34 -0
  311. package/src/dev/client-actions.ts +35 -0
  312. package/src/dev/client-chunk-store.ts +92 -0
  313. package/src/dev/client-key-cache.ts +178 -0
  314. package/src/dev/global-css-cache.ts +212 -0
  315. package/src/dev/imports.ts +2430 -0
  316. package/src/dev/module-cache.ts +721 -0
  317. package/src/dev/module-generations.ts +38 -0
  318. package/src/dev/module-transform.ts +188 -0
  319. package/src/dev/node-module-bundle-cache.ts +63 -0
  320. package/src/dev/restart-cache.ts +10 -0
  321. package/src/dev/route-bundle-key-cache.ts +154 -0
  322. package/src/dev/route-facts-cache.ts +223 -0
  323. package/src/dev/server.ts +1710 -0
  324. package/src/dynamic/source.ts +307 -0
  325. package/src/dynamic/tree-shake.ts +262 -0
  326. package/src/env.ts +92 -0
  327. package/src/extensions.ts +1898 -0
  328. package/src/index.ts +34 -0
  329. package/src/internal.ts +43 -0
  330. package/src/islands/boundary-error.ts +8 -0
  331. package/src/islands/static-children.ts +37 -0
  332. package/src/islands/static-slots.ts +106 -0
  333. package/src/ppr-postpone.ts +24 -0
  334. package/src/ppr.ts +784 -0
  335. package/src/proxy.ts +752 -0
  336. package/src/render/hooks.ts +384 -0
  337. package/src/render/index.ts +1 -0
  338. package/src/render/island-context.ts +47 -0
  339. package/src/render/metadata.ts +857 -0
  340. package/src/render/renderer.ts +7391 -0
  341. package/src/render/resource-hints.ts +44 -0
  342. package/src/render/slots.tsx +679 -0
  343. package/src/request/context.ts +396 -0
  344. package/src/resolve/engine.ts +219 -0
  345. package/src/resolve/imports.ts +1104 -0
  346. package/src/resolve/scan-facts.ts +474 -0
  347. package/src/resolve/source-text.ts +86 -0
  348. package/src/routing/forwarded.ts +41 -0
  349. package/src/routing/handler.ts +271 -0
  350. package/src/routing/href.ts +203 -0
  351. package/src/routing/metadata.ts +1018 -0
  352. package/src/routing/request-runtime.ts +43 -0
  353. package/src/routing/routes.ts +2560 -0
  354. package/src/routing/slots.ts +432 -0
  355. package/src/runtime/server.ts +3453 -0
  356. package/src/runtime/vendor.ts +1160 -0
  357. package/src/style-modules.d.ts +9 -0
  358. package/src/typegen.ts +151 -0
  359. package/src/types.ts +725 -0
  360. package/src/utils/ansi.ts +9 -0
  361. package/src/utils/content-type.ts +31 -0
  362. package/src/utils/decode.ts +7 -0
  363. package/src/utils/dev-profile.ts +31 -0
  364. package/src/utils/error-log.ts +29 -0
  365. package/src/utils/fs-cache.ts +31 -0
  366. package/src/utils/fs.ts +119 -0
  367. package/src/utils/html.ts +46 -0
  368. package/src/utils/serialize.ts +378 -0
  369. package/src/utils/source.ts +35 -0
  370. package/src/utils/verbose.ts +39 -0
  371. package/tsconfig.json +10 -0
@@ -0,0 +1,587 @@
1
+ // Bundler-feature registration (COMPAT - may import core freely).
2
+ //
3
+ // Wires the bundler features into core's bundler seams. All are gated on compat.next, so a pure-core app
4
+ // registers nothing.
5
+ //
6
+ // Features wired here:
7
+ // react-server / next-js conditions -> setServerBundleConditions (core always adds `react-server`;
8
+ // `next-js` gates on cacheComponents)
9
+ // compiler.define / defineServer -> registerServerSourceTransforms (the server graph inlines both;
10
+ // the client graph, owned elsewhere, inlines only `define`)
11
+ // serverExternalPackages/transpile -> setExternalPackagePolicy
12
+ // resolveExtensions -> setResolveExtensions
13
+ //
14
+ // Ownership boundary: the CLIENT-side `compiler.define` merge lives in client/build.ts, not here - this
15
+ // file only handles the SERVER graph.
16
+
17
+ import { realpathSync } from 'node:fs';
18
+ import { readFile } from 'node:fs/promises';
19
+ import path from 'node:path';
20
+ import type { OnLoadResult, Plugin } from 'esbuild';
21
+ import type { ResolvedConfig } from '../../config';
22
+ import type { ServerEsbuildPluginOptions } from '../../extensions';
23
+ import { compatAliases, nextCompatEnabled, rewriteNextFontSource } from '../../compat';
24
+ import {
25
+ getBundlerExtensions,
26
+ getCompatModeExtensions,
27
+ registerClientSourceAsyncPreTransforms,
28
+ registerClientSourceTransforms,
29
+ registerServerSourcePreTransforms,
30
+ registerServerSourceTransforms,
31
+ setAssetExtensions,
32
+ setBundlerExtensions,
33
+ setCompatModeExtensions,
34
+ withSniff,
35
+ } from '../../extensions';
36
+ import {
37
+ isEsmModuleFile,
38
+ isWorkspacePackage,
39
+ packageNameForFile,
40
+ packageNameOfSpecifier,
41
+ resolvePackageImportSpecifier,
42
+ resolvePackageSpecifier,
43
+ setExternalLoadResolver,
44
+ setExternalPackagePolicy,
45
+ setResolveExtensions,
46
+ setTsConfigPath,
47
+ } from '../../resolve/imports';
48
+ import { setServerBundleConditions } from '../../runtime/server';
49
+ import { escapeRegex, specifierSniffTokens } from '../../utils/source';
50
+ import {
51
+ cacheComponentsEnabled,
52
+ compilerDefines,
53
+ esmExternals,
54
+ modularizeImports,
55
+ optimizePackageImports,
56
+ publicRuntimeConfig,
57
+ reactCompilerEnabled,
58
+ relayCompilerConfig,
59
+ removeConsoleTargets,
60
+ resolveExtensions,
61
+ serverExternalPackages,
62
+ swcEnvUsageMode,
63
+ tsconfigPath,
64
+ transpilePackages,
65
+ turbopackResolveAlias,
66
+ } from '../bundler/config';
67
+ import { createModularizeImportsTransform } from '../bundler/modularize-imports';
68
+ import {
69
+ createOptimizePackageImportsTransform,
70
+ optimizedPackageSet,
71
+ } from '../bundler/optimize-package-imports';
72
+ import { createRelayTransform } from '../bundler/relay-transform';
73
+ import {
74
+ polyfillsChunkFileName,
75
+ POLYFILLS_NOMODULE_SOURCE,
76
+ POLYFILL_USAGE_TOKENS,
77
+ rewriteUsagePolyfillImports,
78
+ } from '../bundler/polyfill';
79
+ import { rewriteBunBuiltinExternals } from '../bundler/bun-externals';
80
+ import { clientExternalPackageResolvePlugin } from '../bundler/externals';
81
+ import {
82
+ clientDynamicCommonJsImportsPlugin,
83
+ clientReferenceLoad,
84
+ commonJsDefaultInteropPlugin,
85
+ commonJsInteropEntry,
86
+ recoverCommonJsNamedExportsPlugin,
87
+ rewriteClientDynamicImportPromises,
88
+ rewriteStaticCommonJsNamespaceImports,
89
+ } from '../bundler/cjs-exports';
90
+ import { rewriteImportMetaUrlSource } from '../bundler/import-meta-url';
91
+ import {
92
+ rewriteNewUrlAssetClientSource,
93
+ rewriteNewUrlAssetSource,
94
+ } from '../bundler/new-url-asset';
95
+ import { rewriteReactProfilerImport } from '../bundler/react-compiler';
96
+ import { rewriteRequireContextSource } from '../bundler/require-context';
97
+ import { clientResolveExtensionsPlugin } from '../bundler/resolve-extensions';
98
+ import { tsconfigPathsPlugin } from '../bundler/tsconfig-paths';
99
+ import { fileMemoAsync } from '../bundler/source-cache';
100
+ import { serverSymlinkImportPlugin, symlinkedImportsPossible } from '../bundler/symlink-imports';
101
+ import { registerWasmModuleRuntime, wasmModulePlugin } from '../bundler/wasm';
102
+ import {
103
+ hasWebpackLoaderRuleFor,
104
+ registerWebpackLoaderRuleRuntime,
105
+ rewriteResolveAliasImports,
106
+ webpackLoaderRuleModule,
107
+ webpackLoaderRulesPlugin,
108
+ } from '../bundler/webpack-loaders';
109
+ import { rewriteStaticCompatImports } from '../bundler/static-imports';
110
+ import { createClientWorkerTransform } from '../bundler/worker';
111
+ import { rewriteStyledJsxSource } from '../css/styled-jsx';
112
+ import { getImagesConfig } from '../next/image/config';
113
+ import { appUsesBlurPlaceholder } from '../next/image-usage';
114
+ import { appUsesLegacyLink } from '../next/link-usage';
115
+ import { rewriteLegacyLinkValidation } from '../next/link-validation-transform';
116
+ import { pagesClientModulePlugin } from '../pages/client-plugin';
117
+
118
+ export function registerBundlerExtensions(config: ResolvedConfig): void {
119
+ // The alias registries (setImportAliasExtensions + setModuleAliases) are boot
120
+ // facts — the route scanner and the server runtime latch them before the
121
+ // first compile, so register-boot.ts owns them.
122
+ if (!nextCompatEnabled(config)) return;
123
+
124
+ // B3: user-configured resolver extension order (empty -> core default). The
125
+ // server resolver consumes it via setResolveExtensions; the client esbuild
126
+ // graph gets a probe plugin applying the same order (registered further down
127
+ // with the other client plugins, only when configured).
128
+ const configuredExtensions = resolveExtensions();
129
+ setResolveExtensions(configuredExtensions);
130
+ // A custom `typescript.tsconfigPath` keeps compiler `paths` in a
131
+ // non-default file esbuild never discovers; the client build then needs an
132
+ // explicit resolver plugin (server graph consults setTsConfigPath directly).
133
+ const customTsconfigPath = tsconfigPath();
134
+ setTsConfigPath(customTsconfigPath ? path.resolve(config.root, customTsconfigPath) : undefined);
135
+
136
+ // `turbopack.rules` loader chains: the esbuild-plugin form (webpackLoaderPlugins
137
+ // below) only covers the vendor/client build() passes. The server runtime's
138
+ // per-file SSR loading goes through Bun's own require hooks instead, so a
139
+ // configured rule extension without other pnext handling (e.g. `*.txt`) needs
140
+ // its own registration to preempt Bun's native fallback loader.
141
+ registerWebpackLoaderRuleRuntime(config);
142
+ // Same story for a bare `.wasm` import the server runtime loads directly (a
143
+ // `this.importModule()` target's graph): Bun's native loader has no named
144
+ // exports, so the runtime needs its own instantiating hook.
145
+ registerWasmModuleRuntime(config);
146
+ // A configured loader rule for an image/asset extension must preempt core's generic image/asset
147
+ // resolver so the loader chain runs; core consults `hasLoaderRuleFor` before claiming the extension for
148
+ // its own pipeline, then pulls the chain's output through `loaderRuleModule` - the server graph compiles
149
+ // module-by-module, so there is no onLoad to run it in.
150
+ setAssetExtensions({
151
+ hasLoaderRuleFor: hasWebpackLoaderRuleFor,
152
+ loaderRuleModule: (specifier, importer) => webpackLoaderRuleModule(config, specifier, importer),
153
+ });
154
+
155
+ // B7: external/transpile package policy consulted by the server compile sites.
156
+ const externals = serverExternalPackages();
157
+ const transpile = new Set(transpilePackages());
158
+ setExternalPackagePolicy({
159
+ external: name => externals.has(name),
160
+ transpile: name =>
161
+ !externals.has(name) && (transpile.has(name) || isLinkedWorkspacePackage(config, name)),
162
+ // Linked workspace packages are deliberately absent: esbuild resolves their
163
+ // symlinks to real paths, so they never reach a filter as node_modules.
164
+ transpiled: () => [...transpile].filter(name => !externals.has(name)),
165
+ esmExternals,
166
+ });
167
+ setExternalLoadResolver(({ root, fromFile, specifier, target }) => {
168
+ const packageName = specifier.startsWith('#')
169
+ ? packageNameForFile(fromFile)
170
+ : packageNameOfSpecifier(specifier);
171
+ if (!packageName || !externals.has(packageName)) return undefined;
172
+
173
+ const conditions =
174
+ target === 'client'
175
+ ? ['import', 'browser', 'require', 'default']
176
+ : target === 'edge'
177
+ ? ['react-server', 'edge-light', 'browser', 'module', 'import', 'default']
178
+ : ['node', 'import', 'default'];
179
+ if (specifier.startsWith('#')) {
180
+ return resolvePackageImportSpecifier(root, fromFile, specifier, conditions);
181
+ }
182
+
183
+ const imported = resolvePackageSpecifier(root, fromFile, specifier, conditions);
184
+ if (target === 'client' || !imported || esmExternals() !== true || isEsmModuleFile(imported)) {
185
+ return imported;
186
+ }
187
+ const requireConditions =
188
+ target === 'edge'
189
+ ? ['react-server', 'edge-light', 'browser', 'module', 'require', 'import', 'default']
190
+ : ['node', 'require', 'default'];
191
+ return resolvePackageSpecifier(root, fromFile, specifier, requireConditions) ?? imported;
192
+ });
193
+ // B4/B5(next-js): rendering follows it only with Cache Components; core
194
+ // adds react-server for server vendor bundles.
195
+ setServerBundleConditions(() => (cacheComponentsEnabled() ? ['next-js'] : []));
196
+
197
+ // modularizeImports: split barrel `import { A, B } from '<spec>'` into
198
+ // per-member imports BEFORE path-alias resolution, so the emitted specifiers
199
+ // still flow through tsconfig `paths`. Registered as a server pre-transform
200
+ // (runs ahead of the static-compat alias rewrites below) and a client
201
+ // transform; a no-op when unconfigured.
202
+ const modularize = modularizeImports();
203
+ if (Object.keys(modularize).length > 0) {
204
+ const modularizeTransform = createModularizeImportsTransform(modularize);
205
+ registerServerSourcePreTransforms(modularizeTransform);
206
+ registerClientSourceTransforms(modularizeTransform);
207
+ }
208
+
209
+ // optimizePackageImports: rewrite a barrel package's named imports to the leaf modules its entry
210
+ // re-exports them from, so the vendor pipeline compiles - and the server evaluates - only what the
211
+ // route named. Same chain position as modularizeImports, so the emitted leaf specifiers still flow
212
+ // through alias/path resolution.
213
+ const optimizedPackages = optimizedPackageSet(optimizePackageImports());
214
+ const optimizeTransform = createOptimizePackageImportsTransform(optimizedPackages, config.root);
215
+ registerServerSourcePreTransforms(optimizeTransform);
216
+ registerClientSourceTransforms(optimizeTransform);
217
+
218
+ // compiler.relay: replace `graphql`...`` tagged templates with the artifact
219
+ // relay-compiler generated for the operation. Registered as a pre-transform
220
+ // for the same reason modularizeImports is — the injected artifact imports
221
+ // must still flow through alias/path resolution.
222
+ const relay = relayCompilerConfig();
223
+ if (relay) {
224
+ const relayTransform = createRelayTransform(relay);
225
+ registerServerSourcePreTransforms(relayTransform);
226
+ registerClientSourceTransforms(relayTransform);
227
+ }
228
+
229
+ // Next font/root-params rewrites must precede generic server transforms.
230
+ const fontSniff = ['next/font', 'next/root-params'];
231
+ registerServerSourcePreTransforms(
232
+ withSniff(fontSniff, (source, file, root) =>
233
+ rewriteNextFontSource(source, file, 'server', root),
234
+ ),
235
+ );
236
+ registerClientSourceTransforms(
237
+ withSniff(fontSniff, (source, file, root) =>
238
+ rewriteNextFontSource(source, file, 'client', root),
239
+ ),
240
+ );
241
+ const linkSniff = ['Link', 'legacyBehavior'];
242
+ registerServerSourcePreTransforms(withSniff(linkSniff, rewriteLegacyLinkValidation));
243
+ registerClientSourceTransforms(withSniff(linkSniff, rewriteLegacyLinkValidation));
244
+ registerServerSourcePreTransforms(withSniff(['<style'], rewriteStyledJsxSource));
245
+ registerClientSourceTransforms(withSniff(['<style'], rewriteStyledJsxSource));
246
+ registerServerSourceTransforms(withSniff(["'bun", '"bun'], rewriteBunBuiltinExternals));
247
+ // Materialized fixtures can re-import original sources outside esbuild's
248
+ // alias graph. Keep their static compat imports on the registered facades.
249
+ // Leave React entrypoints for the resolver: RSC/proxy/middleware needs the
250
+ // stricter react-server-layer overrides instead of the ordinary shims.
251
+ const staticServerAliases = compatAliases(config, 'server');
252
+ delete staticServerAliases.react;
253
+ delete staticServerAliases['react-dom'];
254
+ // The CJS facades live in compat/next, one level up from this register dir.
255
+ const nextRoot = path.resolve(import.meta.dirname, '..', 'next');
256
+ const requireAliases = {
257
+ 'next/navigation': path.join(nextRoot, 'navigation.cjs'),
258
+ 'next/router': path.join(nextRoot, 'router.cjs'),
259
+ };
260
+ registerServerSourceTransforms(
261
+ withSniff(
262
+ specifierSniffTokens([...Object.keys(staticServerAliases), ...Object.keys(requireAliases)]),
263
+ (source, file) => rewriteStaticCompatImports(source, file, staticServerAliases, requireAliases),
264
+ ),
265
+ );
266
+ const namespaceImportSniff = [/import\s+\*/];
267
+ registerServerSourceTransforms(withSniff(namespaceImportSniff, rewriteStaticCommonJsNamespaceImports));
268
+ // `turbopack.resolveAlias` bare specifiers: the esbuild/Bun onResolve hooks
269
+ // cover the graphs they own, but Bun's runtime resolver rejects an unknown
270
+ // bare package before plugins run, so modules the server runtime loads
271
+ // directly (a `this.importModule()` target's transitive imports) need the
272
+ // alias applied in source.
273
+ registerServerSourceTransforms(
274
+ withSniff(specifierSniffTokens(Object.keys(turbopackResolveAlias())), (source, file) =>
275
+ rewriteResolveAliasImports(source, file, config.root),
276
+ ),
277
+ );
278
+ registerClientSourceTransforms(withSniff(namespaceImportSniff, rewriteStaticCommonJsNamespaceImports));
279
+
280
+ // B5: compiler.define + compiler.defineServer, both graphs, through the
281
+ // bundler's own `define`. The server graph inlines both; the client graph
282
+ // inlines `define` and folds `defineServer` keys to `undefined` so client
283
+ // fallback branches stay reachable. `define` wins a key present in both.
284
+ const { define, defineServer } = compilerDefines();
285
+ const serverDefines = { ...define, ...defineServer };
286
+ const clientDefines = {
287
+ ...Object.fromEntries(Object.keys(defineServer).map(key => [key, 'undefined'])),
288
+ ...define,
289
+ };
290
+
291
+ // B5: compiler.removeConsole — strip console.* calls from the client graph
292
+ // via esbuild's `pure` option (unused-result calls are dropped in the
293
+ // minified production build).
294
+ const removeConsole = removeConsoleTargets();
295
+
296
+ // experimental.swcEnvOptions: core-js polyfills for the targeted features, on
297
+ // the client graph only — the server graph runs on the current Node/Bun and
298
+ // needs no polyfill.
299
+ if (swcEnvUsageMode()) {
300
+ registerClientSourceTransforms(
301
+ withSniff(POLYFILL_USAGE_TOKENS, (source, file) =>
302
+ rewriteUsagePolyfillImports(source, file, config),
303
+ ),
304
+ );
305
+ }
306
+
307
+ // B: `new URL('./asset.png', import.meta.url)` -> emitted /_next/static/media
308
+ // URL (matching `import img from './asset.png'`.src). Both graphs via a source
309
+ // transform; the client one skips the middleware form and the Profiler pass
310
+ // (registered on its own below).
311
+ registerServerSourceTransforms(
312
+ // `Profiler` too: the new-URL pass front-runs the react-profiler rewrite.
313
+ withSniff(['import.meta.url', 'Profiler'], (source, file) =>
314
+ rewriteNewUrlAssetSource(source, file),
315
+ ),
316
+ );
317
+ registerServerSourceTransforms(withSniff(['import.meta.url'], rewriteImportMetaUrlSource));
318
+ // Client order is load-bearing: the worker pass (async, registered below) and
319
+ // the new-URL asset pass both read `import.meta.url`, which this one inlines.
320
+ registerClientSourceTransforms(
321
+ withSniff(['import.meta.url'], rewriteNewUrlAssetClientSource),
322
+ withSniff(['Profiler'], rewriteReactProfilerImport),
323
+ withSniff([/\.then\s*\(/], source => rewriteClientDynamicImportPromises(source)),
324
+ withSniff(['import.meta.url'], rewriteImportMetaUrlSource),
325
+ );
326
+ // webpack's `require.context(dir, recursive, regExp)`: expanded on disk into static imports plus a
327
+ // synthesized context object. Registered as a source transform, not an esbuild onLoad plugin, so it
328
+ // reaches every consumer of the compiled source without preempting the extension-specific loaders -
329
+ // the server graph through `rewriteServerSource` and the client graph through
330
+ // `applyClientSourceTransforms`.
331
+ const requireContextPaths = { outPath: config.outPath, workspaceRoot: config.workspaceRoot };
332
+ registerServerSourceTransforms(
333
+ withSniff(['.context('], (source, file) =>
334
+ rewriteRequireContextSource(source, file, requireContextPaths),
335
+ ),
336
+ );
337
+ registerClientSourceTransforms(
338
+ withSniff(['.context('], (source, file) =>
339
+ rewriteRequireContextSource(source, file, requireContextPaths),
340
+ ),
341
+ );
342
+ // Web Worker bundling: an async pre-transform, so it sees `import.meta.url`
343
+ // before the sync chain above inlines it. The rest of the chain then runs on
344
+ // its output — no companion re-application needed.
345
+ const workerTransform = createClientWorkerTransform(config, configuredExtensions);
346
+ registerClientSourceAsyncPreTransforms(
347
+ withSniff(['new Worker(', 'new SharedWorker('], (source, file) => workerTransform(source, file)),
348
+ );
349
+
350
+ // next.config's `reactCompiler` is the same switch as pnext's own
351
+ // `compat.reactCompiler`: fold it into the compat-mode options so the single
352
+ // compiler pass (core's client-source loader) sees one answer.
353
+ const priorReactCompilerOptions = getCompatModeExtensions().reactCompilerOptions;
354
+ setCompatModeExtensions({
355
+ reactCompilerOptions: cfg =>
356
+ priorReactCompilerOptions(cfg) ?? (reactCompilerEnabled() ? { target: '18' } : undefined),
357
+ });
358
+
359
+ // Created once, not per build: the memo spans the hundreds of server builds
360
+ // a vendor pass runs over the same workspace sources.
361
+ const firstPartyRewrite = createFirstPartySourceRewrite(config, {
362
+ transform: optimizeTransform,
363
+ sniff: specifierSniffTokens(optimizedPackages),
364
+ });
365
+ const priorClient = getBundlerExtensions().clientEsbuildPlugins;
366
+ const priorServer = getBundlerExtensions().serverEsbuildPlugins;
367
+ const priorPure = getBundlerExtensions().clientPureFunctions;
368
+ setBundlerExtensions({
369
+ clientPureFunctions: cfg => [...priorPure(cfg), ...(removeConsole ?? [])],
370
+ serverDefines: () => serverDefines,
371
+ // The blur gate reads app source, so it is computed on the first client
372
+ // build that asks — never at registration, which runs inside the boot
373
+ // budget. `appUsesBlurPlaceholder` memoizes per root.
374
+ clientDefines: () => ({
375
+ ...clientDefines,
376
+ __PNEXT_IMAGE_BLUR__: String(appUsesBlurPlaceholder(config.root)),
377
+ // Same one-sided source scan for `<Link legacyBehavior>` (link-usage.ts).
378
+ __PNEXT_LINK_LEGACY__: String(appUsesLegacyLink(config.root)),
379
+ // next.config `images` only ever reached the server global, so the client
380
+ // fell back to the defaults — config-dependent props (path, qualities,
381
+ // sizes) mismatched on hydration. Inlining the resolved config also drops
382
+ // the defaults + resolver from every client bundle.
383
+ __PNEXT_IMAGE_CONFIG_INLINE__: JSON.stringify(getImagesConfig()),
384
+ __PNEXT_IMAGE_CONFIG_INLINED__: 'true',
385
+ // publicRuntimeConfig inlined the same way; omitted entirely when unset so an app that
386
+ // never configures it adds zero bytes (unlike images, there is no default to drop).
387
+ ...(Object.keys(publicRuntimeConfig()).length > 0
388
+ ? {
389
+ __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINE__: JSON.stringify(publicRuntimeConfig()),
390
+ __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINED__: 'true',
391
+ }
392
+ : {}),
393
+ }),
394
+ // Next ships a `polyfills-<hash>.js` chunk + a `<script noModule>` tag; the
395
+ // body is inert for pnext's module-capable targets (see polyfill.ts).
396
+ staticClientChunks: () => [
397
+ { name: polyfillsChunkFileName(), contents: POLYFILLS_NOMODULE_SOURCE },
398
+ ],
399
+ clientEsbuildPlugins: (cfg: ResolvedConfig): Plugin[] => [
400
+ ...webpackLoaderPlugins(cfg, 'client'),
401
+ pagesClientModulePlugin(cfg),
402
+ wasmModulePlugin(cfg),
403
+ // tsconfig `paths` resolution for the client graph, whenever any reachable tsconfig declares them:
404
+ // esbuild's native discovery misses standard `tsconfig.json` paths for stdin-based builds and never
405
+ // skips `.d.ts`-first array targets. Everything else stays on esbuild's native resolution.
406
+ ...optional(tsconfigPathsPlugin(cfg)),
407
+ ...(configuredExtensions ? [clientResolveExtensionsPlugin(configuredExtensions)] : []),
408
+ ...optional(clientExternalPackageResolvePlugin(cfg, externals)),
409
+ // First-party source outside every source root gets no
410
+ // registerClientSourceTransforms pass — the OPI rewrite must live here too.
411
+ firstPartyClientOptimizeImportsLoadPlugin(
412
+ cfg,
413
+ optimizeTransform,
414
+ specifierSniffTokens(optimizedPackages),
415
+ ),
416
+ clientDynamicCommonJsImportsPlugin(cfg.root),
417
+ ...priorClient(cfg),
418
+ ],
419
+ serverEsbuildPlugins: (cfg: ResolvedConfig, opts?: ServerEsbuildPluginOptions): Plugin[] => [
420
+ ...webpackLoaderPlugins(cfg, 'server'),
421
+ wasmModulePlugin(cfg),
422
+ ...optional(tsconfigPathsPlugin(cfg)),
423
+ ...(symlinkedImportsPossible(cfg, opts?.realPathEntries)
424
+ ? [serverSymlinkImportPlugin(cfg)]
425
+ : []),
426
+ serverSourceLoadPlugin(firstPartyRewrite, opts?.vendorClientBoundary),
427
+ commonJsDefaultInteropPlugin(),
428
+ recoverCommonJsNamedExportsPlugin(),
429
+ ...priorServer(cfg, opts),
430
+ ],
431
+ serverBundleEntry: commonJsInteropEntry,
432
+ });
433
+ }
434
+
435
+ /** Spread helper for the plugins that skip registration when unconfigured. */
436
+ function optional(plugin: Plugin | undefined): Plugin[] {
437
+ return plugin ? [plugin] : [];
438
+ }
439
+
440
+ function webpackLoaderPlugins(cfg: ResolvedConfig, target: 'client' | 'server'): Plugin[] {
441
+ const plugin = webpackLoaderRulesPlugin(cfg, target);
442
+ return plugin ? [plugin] : [];
443
+ }
444
+
445
+ // Source rewrites a bundle has to get BEFORE resolution, applied where esbuild reads the file:
446
+ // - next/font: vendor bundles transform esbuild's OUTPUT, where `next/font/google` has already been
447
+ // alias-rewritten to a file:// path, so the font rewrite no-ops there and the untouched named imports
448
+ // hit the empty shim.
449
+ // - optimizePackageImports: a `'use client'` component in a LINKED workspace package is compiled by the
450
+ // vendor bundler, which never runs the source-transform chain, so its barrel imports bypassed the
451
+ // rewrite and the whole catalogue was compiled and evaluated.
452
+ // Both are idempotent: re-running either on already-rewritten source is a no-op.
453
+ interface FirstPartySourceRewrite {
454
+ rewrite: (file: string) => Promise<OnLoadResult | undefined>;
455
+ /** node_modules dirs transpilePackages opts back into the rewrite. */
456
+ transpiledFilter?: RegExp;
457
+ }
458
+
459
+ function createFirstPartySourceRewrite(
460
+ config: ResolvedConfig,
461
+ optimize: { transform: (source: string, file: string) => string; sniff: readonly string[] },
462
+ ): FirstPartySourceRewrite {
463
+ const transpiled = transpilePackages();
464
+ const rewrite = fileMemoAsync(async (file: string): Promise<OnLoadResult | undefined> => {
465
+ let source: string;
466
+ try {
467
+ source = await readFile(file, 'utf8');
468
+ } catch {
469
+ return undefined;
470
+ }
471
+ let contents = source;
472
+ if (contents.includes('next/font/')) {
473
+ contents = rewriteNextFontSource(contents, file, 'server', config.root);
474
+ }
475
+ // TS only: what reaches this hook is first-party or transpiled source, and
476
+ // both ship .ts/.tsx. The sniff keeps the parse off everything else.
477
+ if (/\.tsx?$/.test(file) && optimize.sniff.some(token => contents.includes(token))) {
478
+ contents = optimize.transform(contents, file);
479
+ }
480
+ if (contents === source) return undefined;
481
+ // Keep the file's own syntax: `.ts` must not parse as `.tsx` (`<T>`
482
+ // casts), and .js/.mjs/.cjs app source may legitimately contain JSX.
483
+ return { contents, loader: file.endsWith('.ts') ? 'ts' : 'tsx' };
484
+ });
485
+ return {
486
+ rewrite,
487
+ transpiledFilter:
488
+ transpiled.length > 0
489
+ ? new RegExp(`[\\\\/]node_modules[\\\\/](?:${transpiled.map(escapeRegex).join('|')})[\\\\/]`)
490
+ : undefined,
491
+ };
492
+ }
493
+
494
+ /**
495
+ * The server chain's ONE claiming onLoad over JS/TS sources. esbuild hands a file to the FIRST onLoad
496
+ * that claims it, so the three passes that used to be separate plugins - CJS client references, the
497
+ * first-party font/OPI rewrite, and the vendor client-boundary stub - each cost a full callback round
498
+ * trip per input file per build. Composed here in their original registration order, they share one
499
+ * callback.
500
+ */
501
+ function serverSourceLoadPlugin(
502
+ firstParty: FirstPartySourceRewrite,
503
+ vendorClientBoundary?: (file: string) => Promise<OnLoadResult | undefined>,
504
+ ): Plugin {
505
+ return {
506
+ name: 'pnext-server-source-load',
507
+ setup(build) {
508
+ build.onLoad({ filter: /\.[cm]?[jt]sx?$/, namespace: 'file' }, async args => {
509
+ // `use client` in a CommonJS file -> tag its exports as references.
510
+ if (/\.c?js$/.test(args.path)) {
511
+ const references = await clientReferenceLoad(args.path);
512
+ if (references) return references;
513
+ }
514
+ // First-party (or transpilePackages-opted) source: font/OPI rewrites.
515
+ // Everything else under node_modules keeps esbuild's native load path.
516
+ if (
517
+ !args.path.includes(`${path.sep}node_modules${path.sep}`) ||
518
+ firstParty.transpiledFilter?.test(args.path)
519
+ ) {
520
+ const rewritten = await firstParty.rewrite(args.path);
521
+ if (rewritten) return rewritten;
522
+ }
523
+ return vendorClientBoundary?.(args.path);
524
+ });
525
+ },
526
+ };
527
+ }
528
+
529
+ // Client twin of firstPartySourceLoadPlugin, OPI rewrite only (the client pipeline handles next/font
530
+ // itself); same outside-node_modules claim boundary, minus what core's client-source loader already owns.
531
+ // esbuild gives a file to the FIRST onLoad that claims it, and this plugin is registered ahead of that
532
+ // loader - claiming a source root file here would silently drop the whole client chain on it (React
533
+ // Compiler, `dynamic()` rewrite, defines). Under a root the chain applies this same transform anyway;
534
+ // only source living outside every root needs the hook.
535
+ function firstPartyClientOptimizeImportsLoadPlugin(
536
+ config: ResolvedConfig,
537
+ transform: (source: string, file: string) => string,
538
+ sniff: readonly string[],
539
+ ): Plugin {
540
+ const roots = clientSourceRootPrefixes(config);
541
+ const rewriteFile = fileMemoAsync(async (file: string) => {
542
+ let source: string;
543
+ try {
544
+ source = await readFile(file, 'utf8');
545
+ } catch {
546
+ return undefined;
547
+ }
548
+ if (!/\.tsx?$/.test(file) || !sniff.some(token => source.includes(token))) return undefined;
549
+ const contents = transform(source, file);
550
+ if (contents === source) return undefined;
551
+ return { contents, loader: file.endsWith('.ts') ? ('ts' as const) : ('tsx' as const) };
552
+ });
553
+ return {
554
+ name: 'pnext-first-party-client-optimize-imports-load',
555
+ setup(build) {
556
+ build.onLoad({ filter: /\.tsx?$/, namespace: 'file' }, args =>
557
+ args.path.includes(`${path.sep}node_modules${path.sep}`) ||
558
+ roots.some(root => args.path.startsWith(root))
559
+ ? undefined
560
+ : rewriteFile(args.path),
561
+ );
562
+ },
563
+ };
564
+ }
565
+
566
+ // The roots core's client-source loader claims under (client/build.ts
567
+ // `clientSourceRoots`), each with a trailing separator so a sibling directory
568
+ // sharing the prefix is not swallowed.
569
+ function clientSourceRootPrefixes(config: ResolvedConfig): string[] {
570
+ const roots = new Set<string>();
571
+ for (const root of [config.root, config.workspaceRoot]) {
572
+ const resolved = path.resolve(root);
573
+ roots.add(resolved + path.sep);
574
+ try {
575
+ roots.add(realpathSync.native(resolved) + path.sep);
576
+ } catch {
577
+ // Unresolvable root: its literal form already covers the files under it.
578
+ }
579
+ }
580
+ return [...roots];
581
+ }
582
+
583
+ // First-party workspace source is implicitly transpiled. Hoisting puts the
584
+ // package only in the workspace root's node_modules, so both roots are asked.
585
+ function isLinkedWorkspacePackage(config: ResolvedConfig, name: string) {
586
+ return isWorkspacePackage(config.root, name) || isWorkspacePackage(config.workspaceRoot, name);
587
+ }
@@ -0,0 +1,85 @@
1
+ // Cache extension registration (COMPAT - may import core freely).
2
+ //
3
+ // Wires the next/cache compat behavior into the core extension registries so core never statically
4
+ // imports compat/cache/*:
5
+ // - renderExtensions.collectRenderMeta <- collectRenderCacheMeta
6
+ // - requestExtensions.staticStaleness <- pathRevalidatedSince + tagsRevalidatedSince
7
+ // - buildExtensions.initHooks <- installCompatFetchCache (next only)
8
+ // - bundlerExtensions.serverSourceTransforms <- rewriteUseCacheSource
9
+ //
10
+ // Ordering: registerCompatExtensions runs cache BEFORE actions, so the use-cache source transform is
11
+ // registered ahead of the inline-action-tag transform, matching the old rewriteServerSource order.
12
+
13
+ import type { ResolvedConfig } from '../../config';
14
+ import { nextCompatEnabled } from '../../compat';
15
+ import {
16
+ registerBundledSourceTransforms,
17
+ registerInitHooks,
18
+ registerServerSourceTransforms,
19
+ setRenderExtensions,
20
+ setRequestExtensions,
21
+ withSniff,
22
+ } from '../../extensions';
23
+ import {
24
+ collectRenderCacheMeta,
25
+ currentRenderCacheMeta,
26
+ pathRevalidatedSince,
27
+ pathRevalidationReasonSince,
28
+ tagsRevalidatedSince,
29
+ tagsRevalidationReasonSince,
30
+ tagsStaleSince,
31
+ } from '../cache/revalidate';
32
+ import { setBuildFlagsOutPath } from '../cache/build-flags';
33
+ import { installCompatFetchCache } from '../cache/fetch-patch';
34
+ import { installCustomCacheHandler } from '../cache/custom-handler';
35
+ import { installModernCacheHandlers } from '../cache/modern-handler';
36
+ import { rewriteUseCacheSource } from '../cache/use-cache-transform';
37
+ import { resumeDataCacheExtension } from '../cache/resume-data-cache';
38
+
39
+ export function registerCacheExtensions(config: ResolvedConfig): void {
40
+ // Render cache-meta collection scope (tags/revalidate/no-store) wrapped
41
+ // around every prerender + dynamic render; signature matches the registry.
42
+ setRenderExtensions({
43
+ collectRenderMeta: collectRenderCacheMeta,
44
+ // Peek (never consume) the render's aggregated cacheLife stale window, so
45
+ // the document can inline its own reuse window for hard loads.
46
+ currentCacheStaleSeconds: () => currentRenderCacheMeta()?.staleSeconds,
47
+ prerenderSidecar: resumeDataCacheExtension,
48
+ });
49
+
50
+ // ISR on-demand staleness: fold the path + tag revalidation checks start.ts
51
+ // used to OR together into the single registry predicate.
52
+ setRequestExtensions({
53
+ staticStaleness: (pathname, mtimeMs, tags) =>
54
+ pathRevalidatedSince(pathname, mtimeMs) || tagsRevalidatedSince(tags, mtimeMs),
55
+ staticStalenessReason: (pathname, mtimeMs, tags) =>
56
+ pathRevalidationReasonSince(pathname, mtimeMs) ??
57
+ tagsRevalidationReasonSince(tags, mtimeMs) ??
58
+ (tagsStaleSince(tags, mtimeMs) ? 'soft' : undefined),
59
+ });
60
+
61
+ // 'use cache' source rewrite (server bundles): registered first so it runs
62
+ // before the inline-action-tag transform, exactly as before. Also registered
63
+ // over bundled vendor output — a package can ship 'use cache' functions, and
64
+ // the directive is the one trigger in the chain that survives bundling.
65
+ const useCache = withSniff(['use cache'], (source, file, root) =>
66
+ rewriteUseCacheSource(source, file, root),
67
+ );
68
+ registerServerSourceTransforms(useCache);
69
+ registerBundledSourceTransforms(useCache);
70
+
71
+ // Prerenders + runtime renders must observe Next fetch-cache options
72
+ // (force-cache, next: { revalidate, tags }). Idempotent; next-compat only.
73
+ if (nextCompatEnabled(config)) {
74
+ registerInitHooks(cfg => {
75
+ installCompatFetchCache();
76
+ // Where `pnext start` reads the build's --debug-prerender flag back from
77
+ // (the runtime 'use cache' error funnel shapes its log around it).
78
+ setBuildFlagsOutPath(cfg.outPath);
79
+ // Load + instantiate the configured `cacheHandler` (next.config) and
80
+ // install it into the core cache seam so the data cache defers to it.
81
+ installCustomCacheHandler(cfg.root);
82
+ installModernCacheHandlers(cfg.root);
83
+ });
84
+ }
85
+ }