@rangojs/router 0.0.0-experimental.1b930379 → 0.0.0-experimental.1c0bdfad

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 (400) hide show
  1. package/AGENTS.md +12 -0
  2. package/README.md +245 -49
  3. package/dist/bin/rango.js +441 -134
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3453 -1240
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +76 -21
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +64 -2
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +247 -23
  12. package/skills/caching/SKILL.md +318 -15
  13. package/skills/composability/SKILL.md +27 -2
  14. package/skills/css/SKILL.md +76 -0
  15. package/skills/debug-manifest/SKILL.md +4 -2
  16. package/skills/document-cache/SKILL.md +78 -55
  17. package/skills/handler-use/SKILL.md +364 -0
  18. package/skills/hooks/SKILL.md +250 -30
  19. package/skills/host-router/SKILL.md +83 -23
  20. package/skills/i18n/SKILL.md +276 -0
  21. package/skills/intercept/SKILL.md +50 -6
  22. package/skills/layout/SKILL.md +35 -9
  23. package/skills/links/SKILL.md +249 -17
  24. package/skills/loader/SKILL.md +279 -53
  25. package/skills/middleware/SKILL.md +52 -13
  26. package/skills/migrate-nextjs/SKILL.md +584 -0
  27. package/skills/migrate-react-router/SKILL.md +771 -0
  28. package/skills/mime-routes/SKILL.md +28 -1
  29. package/skills/observability/SKILL.md +172 -0
  30. package/skills/parallel/SKILL.md +203 -7
  31. package/skills/prerender/SKILL.md +153 -109
  32. package/skills/rango/SKILL.md +251 -22
  33. package/skills/react-compiler/SKILL.md +168 -0
  34. package/skills/response-routes/SKILL.md +123 -48
  35. package/skills/route/SKILL.md +101 -5
  36. package/skills/router-setup/SKILL.md +116 -8
  37. package/skills/scripts/SKILL.md +179 -0
  38. package/skills/server-actions/SKILL.md +775 -0
  39. package/skills/streams-and-websockets/SKILL.md +283 -0
  40. package/skills/tailwind/SKILL.md +27 -3
  41. package/skills/testing/SKILL.md +129 -0
  42. package/skills/testing/bindings.md +103 -0
  43. package/skills/testing/cache-prerender.md +127 -0
  44. package/skills/testing/client-components.md +124 -0
  45. package/skills/testing/e2e-parity.md +125 -0
  46. package/skills/testing/flight.md +91 -0
  47. package/skills/testing/handles.md +129 -0
  48. package/skills/testing/loader.md +128 -0
  49. package/skills/testing/middleware.md +99 -0
  50. package/skills/testing/render-handler.md +121 -0
  51. package/skills/testing/response-routes.md +95 -0
  52. package/skills/testing/reverse-and-types.md +84 -0
  53. package/skills/testing/server-actions.md +107 -0
  54. package/skills/testing/server-tree.md +128 -0
  55. package/skills/testing/setup.md +123 -0
  56. package/skills/typesafety/SKILL.md +332 -29
  57. package/skills/use-cache/SKILL.md +46 -14
  58. package/skills/view-transitions/SKILL.md +294 -0
  59. package/src/__augment-tests__/augment.ts +81 -0
  60. package/src/__augment-tests__/augmented.check.ts +116 -0
  61. package/src/__internal.ts +1 -66
  62. package/src/browser/action-coordinator.ts +53 -36
  63. package/src/browser/action-fence.ts +47 -0
  64. package/src/browser/app-shell.ts +39 -0
  65. package/src/browser/app-version.ts +14 -0
  66. package/src/browser/connection-warmup.ts +134 -0
  67. package/src/browser/cookie-name.ts +140 -0
  68. package/src/browser/event-controller.ts +197 -150
  69. package/src/browser/history-state.ts +21 -0
  70. package/src/browser/index.ts +3 -3
  71. package/src/browser/invalidate-client-cache.ts +52 -0
  72. package/src/browser/navigation-bridge.ts +111 -31
  73. package/src/browser/navigation-client.ts +201 -67
  74. package/src/browser/navigation-store-handle.ts +38 -0
  75. package/src/browser/navigation-store.ts +76 -67
  76. package/src/browser/navigation-transaction.ts +18 -66
  77. package/src/browser/network-error-handler.ts +34 -7
  78. package/src/browser/partial-update.ts +187 -112
  79. package/src/browser/prefetch/cache.ts +230 -35
  80. package/src/browser/prefetch/fetch.ts +338 -39
  81. package/src/browser/prefetch/queue.ts +126 -20
  82. package/src/browser/prefetch/resource-ready.ts +77 -0
  83. package/src/browser/rango-state.ts +158 -76
  84. package/src/browser/react/Link.tsx +111 -16
  85. package/src/browser/react/NavigationProvider.tsx +135 -120
  86. package/src/browser/react/ScrollRestoration.tsx +10 -6
  87. package/src/browser/react/context.ts +7 -2
  88. package/src/browser/react/filter-segment-order.ts +66 -7
  89. package/src/browser/react/index.ts +0 -48
  90. package/src/browser/react/location-state-shared.ts +178 -8
  91. package/src/browser/react/location-state.ts +39 -14
  92. package/src/browser/react/use-action.ts +6 -15
  93. package/src/browser/react/use-handle.ts +23 -69
  94. package/src/browser/react/use-href.tsx +8 -1
  95. package/src/browser/react/use-link-status.ts +33 -8
  96. package/src/browser/react/use-navigation.ts +32 -7
  97. package/src/browser/react/use-params.ts +20 -10
  98. package/src/browser/react/use-reverse.ts +106 -0
  99. package/src/browser/react/use-router.ts +46 -11
  100. package/src/browser/react/use-search-params.ts +0 -5
  101. package/src/browser/react/use-segments.ts +11 -21
  102. package/src/browser/response-adapter.ts +80 -5
  103. package/src/browser/rsc-router.tsx +218 -76
  104. package/src/browser/scroll-restoration.ts +54 -42
  105. package/src/browser/segment-reconciler.ts +36 -9
  106. package/src/browser/segment-structure-assert.ts +2 -2
  107. package/src/browser/server-action-bridge.ts +222 -61
  108. package/src/browser/types.ts +91 -11
  109. package/src/browser/validate-redirect-origin.ts +43 -16
  110. package/src/build/collect-fallback-refs.ts +107 -0
  111. package/src/build/generate-manifest.ts +65 -40
  112. package/src/build/generate-route-types.ts +5 -1
  113. package/src/build/index.ts +8 -2
  114. package/src/build/prefix-tree-utils.ts +123 -0
  115. package/src/build/route-trie.ts +165 -36
  116. package/src/build/route-types/ast-route-extraction.ts +15 -8
  117. package/src/build/route-types/codegen.ts +16 -5
  118. package/src/build/route-types/include-resolution.ts +125 -24
  119. package/src/build/route-types/param-extraction.ts +6 -3
  120. package/src/build/route-types/per-module-writer.ts +22 -6
  121. package/src/build/route-types/router-processing.ts +272 -96
  122. package/src/build/route-types/scan-filter.ts +9 -2
  123. package/src/build/route-types/source-scan.ts +216 -0
  124. package/src/build/runtime-discovery.ts +9 -20
  125. package/src/cache/cache-error.ts +104 -0
  126. package/src/cache/cache-key-utils.ts +29 -13
  127. package/src/cache/cache-policy.ts +108 -34
  128. package/src/cache/cache-runtime.ts +214 -48
  129. package/src/cache/cache-scope.ts +236 -89
  130. package/src/cache/cache-tag.ts +103 -0
  131. package/src/cache/cf/cf-base64.ts +33 -0
  132. package/src/cache/cf/cf-cache-constants.ts +127 -0
  133. package/src/cache/cf/cf-cache-store.ts +2224 -171
  134. package/src/cache/cf/cf-cache-types.ts +349 -0
  135. package/src/cache/cf/cf-kv-utils.ts +46 -0
  136. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  137. package/src/cache/cf/index.ts +11 -17
  138. package/src/cache/document-cache.ts +89 -27
  139. package/src/cache/handle-snapshot.ts +70 -0
  140. package/src/cache/index.ts +11 -20
  141. package/src/cache/memory-segment-store.ts +136 -37
  142. package/src/cache/profile-registry.ts +31 -31
  143. package/src/cache/read-through-swr.ts +41 -11
  144. package/src/cache/segment-codec.ts +9 -17
  145. package/src/cache/tag-invalidation.ts +230 -0
  146. package/src/cache/taint.ts +55 -0
  147. package/src/cache/types.ts +37 -100
  148. package/src/client.rsc.tsx +44 -21
  149. package/src/client.tsx +119 -290
  150. package/src/cloudflare/index.ts +11 -0
  151. package/src/cloudflare/tracing.ts +109 -0
  152. package/src/component-utils.ts +19 -0
  153. package/src/components/DefaultDocument.tsx +8 -2
  154. package/src/context-var.ts +84 -2
  155. package/src/debug.ts +2 -2
  156. package/src/decode-loader-results.ts +52 -0
  157. package/src/defer.ts +196 -0
  158. package/src/deps/ssr.ts +0 -1
  159. package/src/encode-kv.ts +49 -0
  160. package/src/errors.ts +30 -4
  161. package/src/escape-script.ts +52 -0
  162. package/src/handle.ts +70 -22
  163. package/src/handles/MetaTags.tsx +56 -19
  164. package/src/handles/Scripts.tsx +183 -0
  165. package/src/handles/breadcrumbs.ts +37 -8
  166. package/src/handles/is-thenable.ts +19 -0
  167. package/src/handles/meta.ts +51 -40
  168. package/src/handles/script.ts +244 -0
  169. package/src/host/cookie-handler.ts +9 -60
  170. package/src/host/errors.ts +0 -24
  171. package/src/host/index.ts +8 -2
  172. package/src/host/pattern-matcher.ts +23 -52
  173. package/src/host/router.ts +107 -99
  174. package/src/host/testing.ts +40 -27
  175. package/src/host/types.ts +37 -4
  176. package/src/host/utils.ts +1 -1
  177. package/src/href-client.ts +137 -22
  178. package/src/index.rsc.ts +93 -12
  179. package/src/index.ts +133 -15
  180. package/src/internal-debug.ts +11 -10
  181. package/src/loader-store.ts +500 -0
  182. package/src/loader.rsc.ts +20 -13
  183. package/src/loader.ts +12 -11
  184. package/src/missing-id-error.ts +68 -0
  185. package/src/outlet-context.ts +1 -1
  186. package/src/outlet-provider.tsx +1 -5
  187. package/src/prerender/param-hash.ts +16 -16
  188. package/src/prerender/store.ts +37 -41
  189. package/src/prerender.ts +198 -82
  190. package/src/redirect-origin.ts +100 -0
  191. package/src/regex-escape.ts +8 -0
  192. package/src/render-error-thrower.tsx +20 -0
  193. package/src/response-utils.ts +62 -0
  194. package/src/reverse.ts +65 -15
  195. package/src/root-error-boundary.tsx +1 -19
  196. package/src/route-content-wrapper.tsx +7 -72
  197. package/src/route-definition/dsl-helpers.ts +469 -276
  198. package/src/route-definition/helper-factories.ts +29 -139
  199. package/src/route-definition/helpers-types.ts +113 -37
  200. package/src/route-definition/index.ts +3 -0
  201. package/src/route-definition/redirect.ts +53 -12
  202. package/src/route-definition/resolve-handler-use.ts +161 -0
  203. package/src/route-definition/use-item-types.ts +32 -0
  204. package/src/route-map-builder.ts +7 -17
  205. package/src/route-types.ts +37 -41
  206. package/src/router/basename.ts +14 -0
  207. package/src/router/content-negotiation.ts +164 -17
  208. package/src/router/error-handling.ts +45 -18
  209. package/src/router/find-match.ts +45 -22
  210. package/src/router/handler-context.ts +83 -39
  211. package/src/router/instrument.ts +350 -0
  212. package/src/router/intercept-resolution.ts +50 -24
  213. package/src/router/lazy-includes.ts +19 -53
  214. package/src/router/loader-resolution.ts +274 -56
  215. package/src/router/logging.ts +5 -8
  216. package/src/router/manifest.ts +49 -45
  217. package/src/router/match-api.ts +120 -204
  218. package/src/router/match-context.ts +0 -22
  219. package/src/router/match-handlers.ts +58 -58
  220. package/src/router/match-middleware/background-revalidation.ts +33 -6
  221. package/src/router/match-middleware/cache-lookup.ts +214 -263
  222. package/src/router/match-middleware/cache-store.ts +73 -33
  223. package/src/router/match-middleware/intercept-resolution.ts +8 -28
  224. package/src/router/match-middleware/segment-resolution.ts +52 -18
  225. package/src/router/match-pipelines.ts +1 -42
  226. package/src/router/match-result.ts +104 -40
  227. package/src/router/metrics.ts +5 -34
  228. package/src/router/middleware-types.ts +13 -142
  229. package/src/router/middleware.ts +270 -172
  230. package/src/router/navigation-snapshot.ts +131 -0
  231. package/src/router/params-util.ts +23 -0
  232. package/src/router/pattern-matching.ts +132 -90
  233. package/src/router/prefetch-cache-ttl.ts +51 -0
  234. package/src/router/prerender-match.ts +195 -56
  235. package/src/router/preview-match.ts +32 -102
  236. package/src/router/request-classification.ts +276 -0
  237. package/src/router/revalidation.ts +123 -73
  238. package/src/router/route-snapshot.ts +244 -0
  239. package/src/router/router-context.ts +8 -28
  240. package/src/router/router-interfaces.ts +115 -35
  241. package/src/router/router-options.ts +172 -15
  242. package/src/router/router-registry.ts +2 -5
  243. package/src/router/segment-resolution/fresh.ts +264 -77
  244. package/src/router/segment-resolution/helpers.ts +115 -30
  245. package/src/router/segment-resolution/loader-cache.ts +63 -37
  246. package/src/router/segment-resolution/revalidation.ts +474 -385
  247. package/src/router/segment-resolution/static-store.ts +19 -5
  248. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  249. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  250. package/src/router/segment-resolution.ts +5 -1
  251. package/src/router/segment-wrappers.ts +8 -5
  252. package/src/router/state-cookie-name.ts +33 -0
  253. package/src/router/substitute-pattern-params.ts +56 -0
  254. package/src/router/telemetry-otel.ts +161 -199
  255. package/src/router/telemetry.ts +96 -19
  256. package/src/router/timeout.ts +0 -20
  257. package/src/router/tracing.ts +206 -0
  258. package/src/router/trie-matching.ts +163 -59
  259. package/src/router/types.ts +10 -63
  260. package/src/router/url-params.ts +44 -0
  261. package/src/router.ts +163 -55
  262. package/src/rsc/handler-context.ts +3 -2
  263. package/src/rsc/handler.ts +658 -511
  264. package/src/rsc/helpers.ts +168 -46
  265. package/src/rsc/index.ts +2 -5
  266. package/src/rsc/json-route-result.ts +38 -0
  267. package/src/rsc/loader-fetch.ts +127 -31
  268. package/src/rsc/manifest-init.ts +33 -42
  269. package/src/rsc/origin-guard.ts +39 -25
  270. package/src/rsc/progressive-enhancement.ts +77 -11
  271. package/src/rsc/redirect-guard.ts +99 -0
  272. package/src/rsc/response-cache-serve.ts +238 -0
  273. package/src/rsc/response-error.ts +79 -12
  274. package/src/rsc/response-route-handler.ts +99 -189
  275. package/src/rsc/rsc-rendering.ts +105 -72
  276. package/src/rsc/runtime-warnings.ts +23 -10
  277. package/src/rsc/server-action.ts +263 -112
  278. package/src/rsc/ssr-setup.ts +18 -2
  279. package/src/rsc/types.ts +32 -6
  280. package/src/runtime-env.ts +18 -0
  281. package/src/search-params.ts +35 -30
  282. package/src/segment-content-promise.ts +67 -0
  283. package/src/segment-loader-promise.ts +149 -0
  284. package/src/segment-system.tsx +281 -129
  285. package/src/serialize.ts +243 -0
  286. package/src/server/context.ts +309 -61
  287. package/src/server/cookie-parse.ts +32 -0
  288. package/src/server/cookie-store.ts +80 -5
  289. package/src/server/handle-store.ts +40 -38
  290. package/src/server/loader-registry.ts +26 -46
  291. package/src/server/request-context.ts +398 -172
  292. package/src/ssr/index.tsx +25 -16
  293. package/src/static-handler.ts +27 -18
  294. package/src/testing/cache-status.ts +162 -0
  295. package/src/testing/collect-handle.ts +40 -0
  296. package/src/testing/dispatch.ts +701 -0
  297. package/src/testing/dom.entry.ts +22 -0
  298. package/src/testing/e2e/fixture.ts +188 -0
  299. package/src/testing/e2e/index.ts +128 -0
  300. package/src/testing/e2e/matchers.ts +35 -0
  301. package/src/testing/e2e/page-helpers.ts +272 -0
  302. package/src/testing/e2e/parity.ts +387 -0
  303. package/src/testing/e2e/server.ts +195 -0
  304. package/src/testing/flight-matchers.ts +97 -0
  305. package/src/testing/flight-normalize.ts +11 -0
  306. package/src/testing/flight-runtime.d.ts +57 -0
  307. package/src/testing/flight-tree.ts +682 -0
  308. package/src/testing/flight.entry.ts +52 -0
  309. package/src/testing/flight.ts +257 -0
  310. package/src/testing/generated-routes.ts +183 -0
  311. package/src/testing/index.ts +99 -0
  312. package/src/testing/internal/context.ts +371 -0
  313. package/src/testing/internal/flight-client-globals.ts +30 -0
  314. package/src/testing/internal/seed-vars.ts +54 -0
  315. package/src/testing/render-handler.ts +343 -0
  316. package/src/testing/render-route.tsx +581 -0
  317. package/src/testing/run-loader.ts +385 -0
  318. package/src/testing/run-middleware.ts +205 -0
  319. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  320. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  321. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  322. package/src/testing/vitest-stubs/version.ts +5 -0
  323. package/src/testing/vitest.ts +305 -0
  324. package/src/theme/ThemeProvider.tsx +20 -58
  325. package/src/theme/ThemeScript.tsx +7 -9
  326. package/src/theme/constants.ts +52 -13
  327. package/src/theme/index.ts +0 -7
  328. package/src/theme/theme-context.ts +1 -5
  329. package/src/theme/theme-script.ts +22 -21
  330. package/src/theme/use-theme.ts +0 -3
  331. package/src/types/boundaries.ts +0 -35
  332. package/src/types/cache-types.ts +17 -8
  333. package/src/types/error-types.ts +30 -90
  334. package/src/types/global-namespace.ts +54 -41
  335. package/src/types/handler-context.ts +233 -81
  336. package/src/types/index.ts +1 -10
  337. package/src/types/loader-types.ts +44 -15
  338. package/src/types/request-scope.ts +112 -0
  339. package/src/types/route-config.ts +6 -50
  340. package/src/types/route-entry.ts +19 -7
  341. package/src/types/segments.ts +37 -14
  342. package/src/urls/include-helper.ts +33 -70
  343. package/src/urls/index.ts +1 -11
  344. package/src/urls/path-helper-types.ts +58 -11
  345. package/src/urls/path-helper.ts +57 -111
  346. package/src/urls/pattern-types.ts +48 -19
  347. package/src/urls/response-types.ts +25 -22
  348. package/src/urls/type-extraction.ts +58 -139
  349. package/src/urls/urls-function.ts +1 -18
  350. package/src/use-loader.tsx +346 -89
  351. package/src/vite/debug.ts +185 -0
  352. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  353. package/src/vite/discovery/discover-routers.ts +130 -85
  354. package/src/vite/discovery/discovery-errors.ts +194 -0
  355. package/src/vite/discovery/gate-state.ts +171 -0
  356. package/src/vite/discovery/prerender-collection.ts +214 -132
  357. package/src/vite/discovery/route-types-writer.ts +40 -84
  358. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  359. package/src/vite/discovery/state.ts +57 -6
  360. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  361. package/src/vite/index.ts +6 -0
  362. package/src/vite/inject-client-debug.ts +36 -0
  363. package/src/vite/plugin-types.ts +155 -65
  364. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  365. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  366. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  367. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  368. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  369. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  370. package/src/vite/plugins/expose-action-id.ts +49 -98
  371. package/src/vite/plugins/expose-id-utils.ts +96 -51
  372. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  373. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  374. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  375. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  376. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  377. package/src/vite/plugins/performance-tracks.ts +89 -0
  378. package/src/vite/plugins/refresh-cmd.ts +89 -27
  379. package/src/vite/plugins/use-cache-transform.ts +73 -83
  380. package/src/vite/plugins/version-injector.ts +21 -25
  381. package/src/vite/plugins/version-plugin.ts +46 -37
  382. package/src/vite/plugins/virtual-entries.ts +13 -18
  383. package/src/vite/rango.ts +238 -295
  384. package/src/vite/router-discovery.ts +940 -149
  385. package/src/vite/utils/ast-handler-extract.ts +26 -35
  386. package/src/vite/utils/banner.ts +4 -4
  387. package/src/vite/utils/bundle-analysis.ts +10 -15
  388. package/src/vite/utils/client-chunks.ts +184 -0
  389. package/src/vite/utils/directive-prologue.ts +40 -0
  390. package/src/vite/utils/forward-user-plugins.ts +171 -0
  391. package/src/vite/utils/manifest-utils.ts +4 -59
  392. package/src/vite/utils/package-resolution.ts +20 -52
  393. package/src/vite/utils/prerender-utils.ts +81 -34
  394. package/src/vite/utils/shared-utils.ts +92 -42
  395. package/src/browser/action-response-classifier.ts +0 -99
  396. package/src/browser/react/use-client-cache.ts +0 -58
  397. package/src/browser/shallow.ts +0 -40
  398. package/src/handles/index.ts +0 -7
  399. package/src/network-error-thrower.tsx +0 -23
  400. package/src/router/middleware-cookies.ts +0 -55
package/src/vite/rango.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PluginOption } from "vite";
1
+ import { type PluginOption } from "vite";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { exposeActionId } from "./plugins/expose-action-id.js";
@@ -12,27 +12,37 @@ import { VIRTUAL_IDS } from "./plugins/virtual-entries.js";
12
12
  import {
13
13
  getExcludeDeps,
14
14
  getPackageAliases,
15
+ getPublishedPackageName,
16
+ getVendorAliases,
15
17
  } from "./utils/package-resolution.js";
16
- import {
17
- createScanFilter,
18
- findRouterFiles,
19
- } from "../build/generate-route-types.js";
18
+ import { findRouterFiles } from "../build/generate-route-types.js";
20
19
  import { createVersionPlugin } from "./plugins/version-plugin.js";
21
20
  import {
22
- sharedEsbuildOptions,
21
+ sharedRolldownOptions,
23
22
  createVirtualEntriesPlugin,
24
23
  onwarn,
25
24
  getManualChunks,
26
25
  } from "./utils/shared-utils.js";
27
- import type {
28
- RangoOptions,
29
- RangoNodeOptions,
30
- RscPluginOptions,
31
- } from "./plugin-types.js";
26
+ import {
27
+ resolveClientChunks,
28
+ type ClientChunkContext,
29
+ } from "./utils/client-chunks.js";
30
+ import type { RangoOptions } from "./plugin-types.js";
32
31
  import { printBanner, rangoVersion } from "./utils/banner.js";
33
32
  import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
34
33
  import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
35
34
  import { createRouterDiscoveryPlugin } from "./router-discovery.js";
35
+ import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
36
+ import { createRangoDebugger, NS } from "./debug.js";
37
+
38
+ const debugConfig = createRangoDebugger(NS.config);
39
+
40
+ // The leading-directive 'use client' sniff is shared with version-plugin's
41
+ // getClientModuleSignature so the two cannot drift. Imported for local use by the
42
+ // HMR transform below and re-exported because the E8 sniff test imports it from
43
+ // this module.
44
+ import { hasUseClientDirective } from "./utils/directive-prologue.js";
45
+ export { hasUseClientDirective };
36
46
 
37
47
  /**
38
48
  * Vite plugin for @rangojs/router.
@@ -43,7 +53,7 @@ import { createRouterDiscoveryPlugin } from "./router-discovery.js";
43
53
  * @example Node.js (default)
44
54
  * ```ts
45
55
  * export default defineConfig({
46
- * plugins: [react(), rango({ router: './src/router.tsx' })],
56
+ * plugins: [react(), rango()],
47
57
  * });
48
58
  * ```
49
59
  *
@@ -59,18 +69,46 @@ import { createRouterDiscoveryPlugin } from "./router-discovery.js";
59
69
  * ```
60
70
  */
61
71
  export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
72
+ const rangoStart = performance.now();
62
73
  const resolvedOptions: RangoOptions = options ?? { preset: "node" };
63
74
  const preset = resolvedOptions.preset ?? "node";
64
75
  const showBanner = resolvedOptions.banner ?? true;
76
+ const clientChunksOption = resolvedOptions.clientChunks ?? true;
77
+ const useBuiltInClientChunks = clientChunksOption === true;
78
+ const clientChunkCtx: ClientChunkContext | undefined = useBuiltInClientChunks
79
+ ? { fallbackRefs: new Set<string>() }
80
+ : undefined;
81
+ const clientChunks = resolveClientChunks(clientChunksOption, clientChunkCtx);
82
+ debugConfig?.("rango(%s) setup start", preset);
65
83
 
66
84
  const plugins: PluginOption[] = [];
67
85
 
68
- // Get package resolution info (workspace vs npm install)
69
- const rangoAliases = getPackageAliases();
70
- const excludeDeps = getExcludeDeps();
71
-
72
- // Track RSC entry path for version injection
73
- let rscEntryPath: string | null = null;
86
+ // Get package resolution info (workspace vs npm install).
87
+ // Vendor aliases redirect the bare plugin-rsc vendor specs (which plugin-rsc
88
+ // itself injects into optimizeDeps.include) to absolute paths resolved from
89
+ // this package — so strict-pnpm consumers don't hit "Failed to resolve
90
+ // dependency" warnings when those deps aren't hoisted to their app root.
91
+ const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
92
+ const excludeDeps = [
93
+ ...getExcludeDeps(),
94
+ // plugin-rsc itself injects these into the client env's
95
+ // optimizeDeps.include, which overrides exclude for the dep's own
96
+ // pre-bundle entry. What exclude still controls is how *other*
97
+ // pre-bundled deps treat imports of these specs (external vs inlined)
98
+ // via esbuildCjsExternalPlugin. The cjs-to-esm transform in
99
+ // plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
100
+ // where client.browser's bare include fails to resolve and Vite ends up
101
+ // serving the raw CJS file at dev-serve time.
102
+ "@vitejs/plugin-rsc/browser",
103
+ "@vitejs/plugin-rsc/vendor/react-server-dom/client.browser",
104
+ ];
105
+
106
+ // Vite supports a nested `A > B` syntax in optimizeDeps.include that resolves
107
+ // B from A's location. We anchor transitive deps (rsc-html-stream,
108
+ // @vitejs/plugin-rsc/vendor/*) to @rangojs/router so pnpm consumers — where
109
+ // these aren't visible at the app root — can still pre-bundle them.
110
+ const pkg = getPublishedPackageName();
111
+ const nested = (spec: string) => `${pkg} > ${spec}`;
74
112
 
75
113
  // Mutable ref for router path (node preset only).
76
114
  // Set immediately when user-specified, or populated by the auto-discover
@@ -82,14 +120,8 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
82
120
  const prerenderEnabled = true;
83
121
 
84
122
  if (preset === "cloudflare") {
85
- // Cloudflare preset: configure entries for cloudflare worker setup
86
- // Router is not needed here - worker.rsc.tsx imports it directly
87
-
88
- // Dynamically import @vitejs/plugin-rsc
89
123
  const { default: rsc } = await import("@vitejs/plugin-rsc");
90
124
 
91
- // Only client and ssr entries - rsc entry is handled by cloudflare plugin
92
- // Always use virtual modules for cloudflare preset
93
125
  const finalEntries: { client: string; ssr: string } = {
94
126
  client: VIRTUAL_IDS.browser,
95
127
  ssr: VIRTUAL_IDS.ssr,
@@ -100,16 +132,21 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
100
132
  enforce: "pre",
101
133
 
102
134
  config() {
103
- // Configure environments for cloudflare deployment
104
135
  return {
105
- // Exclude rsc-router modules from optimization to prevent module duplication
106
- // This ensures the same Context instance is used by both browser entry and RSC proxy modules
107
136
  optimizeDeps: {
108
137
  exclude: excludeDeps,
109
- esbuildOptions: sharedEsbuildOptions,
138
+ rolldownOptions: sharedRolldownOptions,
110
139
  },
111
140
  resolve: {
112
141
  alias: rangoAliases,
142
+ // Force a single React/React-DOM copy across all three RSC
143
+ // environments. RSC requires exactly one react/react-dom instance
144
+ // per environment runtime; consumer install topologies (pnpm
145
+ // strict layout, experimental React pins, third-party "use client"
146
+ // packages) can otherwise resolve duplicate copies, causing
147
+ // "Invalid hook call" / lost context. Child environments inherit
148
+ // this root dedupe, and Vite merges it with any consumer dedupe.
149
+ dedupe: ["react", "react-dom"],
113
150
  },
114
151
  build: {
115
152
  rollupOptions: { onwarn },
@@ -118,30 +155,22 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
118
155
  client: {
119
156
  build: {
120
157
  rollupOptions: {
158
+ onwarn,
121
159
  output: {
122
160
  manualChunks: getManualChunks,
123
161
  },
124
162
  },
125
163
  },
126
- // Pre-bundle rsc-html-stream to prevent discovery during first request
127
- // Exclude rsc-router modules to ensure same Context instance
128
164
  optimizeDeps: {
129
- include: ["rsc-html-stream/client"],
165
+ include: [nested("rsc-html-stream/client")],
130
166
  exclude: excludeDeps,
131
- esbuildOptions: sharedEsbuildOptions,
167
+ rolldownOptions: sharedRolldownOptions,
132
168
  },
133
169
  },
134
170
  ssr: {
135
- // Build SSR inside RSC directory so wrangler can deploy self-contained dist/rsc
136
171
  build: {
137
172
  outDir: "./dist/rsc/ssr",
138
173
  },
139
- resolve: {
140
- // Ensure single React instance in SSR child environment
141
- dedupe: ["react", "react-dom"],
142
- },
143
- // Pre-bundle SSR entry and React for proper module linking with childEnvironments
144
- // All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
145
174
  optimizeDeps: {
146
175
  entries: [finalEntries.ssr],
147
176
  include: [
@@ -151,26 +180,27 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
151
180
  "react-dom/static.edge",
152
181
  "react/jsx-runtime",
153
182
  "react/jsx-dev-runtime",
154
- "rsc-html-stream/server",
155
- "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
183
+ nested("rsc-html-stream/server"),
184
+ nested(
185
+ "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
186
+ ),
156
187
  ],
157
188
  exclude: excludeDeps,
158
- esbuildOptions: sharedEsbuildOptions,
189
+ rolldownOptions: sharedRolldownOptions,
159
190
  },
160
191
  },
161
192
  rsc: {
162
- // RSC environment needs exclude list and esbuild options
163
- // Exclude rsc-router modules to prevent createContext in RSC environment
164
193
  optimizeDeps: {
165
- // Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
166
194
  include: [
167
195
  "react",
168
196
  "react/jsx-runtime",
169
197
  "react/jsx-dev-runtime",
170
- "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
198
+ nested(
199
+ "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
200
+ ),
171
201
  ],
172
202
  exclude: excludeDeps,
173
- esbuildOptions: sharedEsbuildOptions,
203
+ rolldownOptions: sharedRolldownOptions,
174
204
  },
175
205
  },
176
206
  },
@@ -191,232 +221,176 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
191
221
  });
192
222
 
193
223
  plugins.push(createVirtualEntriesPlugin(finalEntries));
194
-
195
- // Add RSC plugin with cloudflare-specific options
196
- // Note: loadModuleDevProxy should NOT be used with childEnvironments
197
- // since SSR runs in workerd alongside RSC
224
+ plugins.push(performanceTracksPlugin());
198
225
  plugins.push(
199
226
  rsc({
200
227
  entries: finalEntries,
201
228
  serverHandler: false,
229
+ clientChunks,
202
230
  }) as PluginOption,
203
231
  );
204
-
205
- // Deduplicate client references from third-party packages in dev mode.
206
- // Prevents module duplication when server components import "use client"
207
- // packages that are also imported directly by client components.
208
232
  plugins.push(clientRefDedup());
209
233
  } else {
210
- // Node preset: full RSC plugin integration
211
- const nodeOptions = resolvedOptions as RangoNodeOptions;
212
-
213
- routerRef.path = nodeOptions.router;
214
-
215
- // Auto-discover router using Vite's resolved root (not process.cwd())
216
- if (!routerRef.path) {
217
- plugins.push({
218
- name: "@rangojs/router:auto-discover",
219
- config(userConfig) {
220
- if (routerRef.path) return;
221
- const root = userConfig.root
222
- ? resolve(process.cwd(), userConfig.root)
223
- : process.cwd();
224
- const filter = createScanFilter(root, {
225
- include: resolvedOptions.include,
226
- exclude: resolvedOptions.exclude,
227
- });
228
- const candidates = findRouterFiles(root, filter);
229
- if (candidates.length === 1) {
230
- const abs = candidates[0];
231
- routerRef.path = (
232
- abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs
233
- ).replaceAll("\\", "/");
234
- } else if (candidates.length > 1) {
235
- const list = candidates
236
- .map(
237
- (f) =>
238
- " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
239
- )
240
- .join("\n");
241
- throw new Error(
242
- `[rsc-router] Multiple routers found. Specify \`router\` to choose one:\n${list}`,
243
- );
244
- }
245
- // 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
246
- },
247
- });
248
- }
249
-
250
- const rscOption = nodeOptions.rsc ?? true;
251
-
252
- // Add RSC plugin by default (can be disabled with rsc: false)
253
- if (rscOption !== false) {
254
- // Dynamically import @vitejs/plugin-rsc
255
- const { default: rsc } = await import("@vitejs/plugin-rsc");
256
-
257
- // Resolve entry paths: use explicit config or virtual modules
258
- const userEntries =
259
- typeof rscOption === "boolean" ? {} : rscOption.entries || {};
260
- const finalEntries = {
261
- client: userEntries.client ?? VIRTUAL_IDS.browser,
262
- ssr: userEntries.ssr ?? VIRTUAL_IDS.ssr,
263
- rsc: userEntries.rsc ?? VIRTUAL_IDS.rsc,
264
- };
234
+ plugins.push({
235
+ name: "@rangojs/router:auto-discover",
236
+ config(userConfig) {
237
+ if (routerRef.path) return;
238
+ const root = userConfig.root
239
+ ? resolve(process.cwd(), userConfig.root)
240
+ : process.cwd();
241
+ const candidates = findRouterFiles(root);
242
+ if (candidates.length === 1) {
243
+ const abs = candidates[0];
244
+ routerRef.path = (
245
+ abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs
246
+ ).replaceAll("\\", "/");
247
+ } else if (candidates.length > 1) {
248
+ const list = candidates
249
+ .map(
250
+ (f) =>
251
+ " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
252
+ )
253
+ .join("\n");
254
+ throw new Error(`[rango] Multiple routers found:\n${list}`);
255
+ }
256
+ },
257
+ });
265
258
 
266
- // Track RSC entry for version injection (only if custom entry provided)
267
- rscEntryPath = userEntries.rsc ?? null;
259
+ const finalEntries = {
260
+ client: VIRTUAL_IDS.browser,
261
+ ssr: VIRTUAL_IDS.ssr,
262
+ rsc: VIRTUAL_IDS.rsc,
263
+ };
268
264
 
269
- // Create wrapper plugin that checks for duplicates
270
- let hasWarnedDuplicate = false;
265
+ const { default: rsc } = await import("@vitejs/plugin-rsc");
271
266
 
272
- plugins.push({
273
- name: "@rangojs/router:rsc-integration",
274
- enforce: "pre",
267
+ let hasWarnedDuplicate = false;
275
268
 
276
- config() {
277
- // Configure environments for RSC
278
- // When using virtual entries, we need to explicitly configure optimizeDeps
279
- // so Vite pre-bundles React before processing the virtual modules.
280
- // Without this, the dep optimizer may run multiple times with different hashes,
281
- // causing React instance mismatches.
282
- const useVirtualClient = finalEntries.client === VIRTUAL_IDS.browser;
283
- const useVirtualSSR = finalEntries.ssr === VIRTUAL_IDS.ssr;
284
- const useVirtualRSC = finalEntries.rsc === VIRTUAL_IDS.rsc;
269
+ plugins.push({
270
+ name: "@rangojs/router:rsc-integration",
271
+ enforce: "pre",
285
272
 
286
- return {
287
- // Exclude rsc-router modules from optimization to prevent module duplication
288
- // This ensures the same Context instance is used by both browser entry and RSC proxy modules
289
- optimizeDeps: {
290
- exclude: excludeDeps,
291
- esbuildOptions: sharedEsbuildOptions,
292
- },
293
- build: {
294
- rollupOptions: { onwarn },
295
- },
296
- resolve: {
297
- alias: rangoAliases,
298
- },
299
- environments: {
300
- client: {
301
- build: {
302
- rollupOptions: {
303
- output: {
304
- manualChunks: getManualChunks,
305
- },
273
+ config() {
274
+ return {
275
+ optimizeDeps: {
276
+ exclude: excludeDeps,
277
+ rolldownOptions: sharedRolldownOptions,
278
+ },
279
+ build: {
280
+ rollupOptions: { onwarn },
281
+ },
282
+ resolve: {
283
+ alias: rangoAliases,
284
+ // Force a single React/React-DOM copy across all three RSC
285
+ // environments. RSC requires exactly one react/react-dom instance
286
+ // per environment runtime; consumer install topologies (pnpm
287
+ // strict layout, experimental React pins, third-party "use client"
288
+ // packages) can otherwise resolve duplicate copies, causing
289
+ // "Invalid hook call" / lost context. Child environments inherit
290
+ // this root dedupe, and Vite merges it with any consumer dedupe.
291
+ dedupe: ["react", "react-dom"],
292
+ },
293
+ environments: {
294
+ client: {
295
+ build: {
296
+ rollupOptions: {
297
+ onwarn,
298
+ output: {
299
+ manualChunks: getManualChunks,
306
300
  },
307
301
  },
308
- // Always exclude rsc-router modules, conditionally add virtual entry
309
- optimizeDeps: {
310
- // Pre-bundle React and rsc-html-stream to prevent late discovery
311
- // triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
312
- include: [
313
- "react",
314
- "react-dom",
315
- "react/jsx-runtime",
316
- "react/jsx-dev-runtime",
317
- "rsc-html-stream/client",
318
- ],
319
- exclude: excludeDeps,
320
- esbuildOptions: sharedEsbuildOptions,
321
- ...(useVirtualClient && {
322
- // Tell Vite to scan the virtual entry for dependencies
323
- entries: [VIRTUAL_IDS.browser],
324
- }),
325
- },
326
302
  },
327
- ...(useVirtualSSR && {
328
- ssr: {
329
- optimizeDeps: {
330
- entries: [VIRTUAL_IDS.ssr],
331
- // Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
332
- include: [
333
- "react",
334
- "react-dom",
335
- "react-dom/server.edge",
336
- "react-dom/static.edge",
337
- "react/jsx-runtime",
338
- "react/jsx-dev-runtime",
339
- "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
340
- ],
341
- exclude: excludeDeps,
342
- esbuildOptions: sharedEsbuildOptions,
343
- },
344
- },
345
- }),
346
- ...(useVirtualRSC && {
347
- rsc: {
348
- optimizeDeps: {
349
- entries: [VIRTUAL_IDS.rsc],
350
- // Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
351
- include: [
352
- "react",
353
- "react/jsx-runtime",
354
- "react/jsx-dev-runtime",
355
- "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
356
- ],
357
- esbuildOptions: sharedEsbuildOptions,
358
- },
359
- },
360
- }),
303
+ optimizeDeps: {
304
+ include: [
305
+ "react",
306
+ "react-dom",
307
+ "react/jsx-runtime",
308
+ "react/jsx-dev-runtime",
309
+ nested("rsc-html-stream/client"),
310
+ ],
311
+ exclude: excludeDeps,
312
+ rolldownOptions: sharedRolldownOptions,
313
+ entries: [VIRTUAL_IDS.browser],
314
+ },
361
315
  },
362
- };
363
- },
364
-
365
- configResolved(config) {
366
- if (showBanner) {
367
- const mode =
368
- config.command === "serve"
369
- ? process.argv.includes("preview")
370
- ? "preview"
371
- : "dev"
372
- : "build";
373
- printBanner(mode, "node", rangoVersion);
374
- }
375
-
376
- // Count how many RSC base plugins there are (rsc:minimal is the main one)
377
- const rscMinimalCount = config.plugins.filter(
378
- (p) => p.name === "rsc:minimal",
379
- ).length;
316
+ ssr: {
317
+ optimizeDeps: {
318
+ entries: [VIRTUAL_IDS.ssr],
319
+ include: [
320
+ "react",
321
+ "react-dom",
322
+ "react-dom/server.edge",
323
+ "react-dom/static.edge",
324
+ "react/jsx-runtime",
325
+ "react/jsx-dev-runtime",
326
+ nested(
327
+ "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
328
+ ),
329
+ ],
330
+ exclude: excludeDeps,
331
+ rolldownOptions: sharedRolldownOptions,
332
+ },
333
+ },
334
+ rsc: {
335
+ optimizeDeps: {
336
+ entries: [VIRTUAL_IDS.rsc],
337
+ include: [
338
+ "react",
339
+ "react/jsx-runtime",
340
+ "react/jsx-dev-runtime",
341
+ nested(
342
+ "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
343
+ ),
344
+ ],
345
+ // Vite 8 does not propagate the top-level optimizeDeps.exclude
346
+ // (set in config()) to non-client envs, so the rsc env must set
347
+ // it explicitly — mirroring the node ssr env and the cloudflare
348
+ // rsc env. Without it a strict-pnpm npm-installed app can try to
349
+ // pre-bundle the router's own subpath entries and fail.
350
+ exclude: excludeDeps,
351
+ rolldownOptions: sharedRolldownOptions,
352
+ },
353
+ },
354
+ },
355
+ };
356
+ },
380
357
 
381
- if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
382
- hasWarnedDuplicate = true;
383
- console.warn(
384
- "[rsc-router] Duplicate @vitejs/plugin-rsc detected. " +
385
- "Remove rsc() from your config or use rango({ rsc: false }) for manual configuration.",
386
- );
387
- }
388
- },
389
- });
358
+ configResolved(config) {
359
+ if (showBanner) {
360
+ const mode =
361
+ config.command === "serve"
362
+ ? process.argv.includes("preview")
363
+ ? "preview"
364
+ : "dev"
365
+ : "build";
366
+ printBanner(mode, "node", rangoVersion);
367
+ }
390
368
 
391
- // Add virtual entries plugin (RSC entry generated lazily from routerRef)
392
- plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
369
+ const rscMinimalCount = config.plugins.filter(
370
+ (p) => p.name === "rsc:minimal",
371
+ ).length;
393
372
 
394
- // Add the RSC plugin directly
395
- // Cast to PluginOption to handle type differences between bundled vite types
396
- plugins.push(
397
- rsc({
398
- entries: finalEntries,
399
- }) as PluginOption,
400
- );
401
- }
373
+ if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
374
+ hasWarnedDuplicate = true;
375
+ console.warn(
376
+ "[rango] Duplicate @vitejs/plugin-rsc detected. " +
377
+ "Remove rsc() from your vite config — rango() includes it automatically.",
378
+ );
379
+ }
380
+ },
381
+ });
402
382
 
403
- // Deduplicate client references from third-party packages in dev mode.
404
- // Prevents module duplication when server components import "use client"
405
- // packages that are also imported directly by client components.
383
+ plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
384
+ plugins.push(performanceTracksPlugin());
385
+ plugins.push(
386
+ rsc({
387
+ entries: finalEntries,
388
+ clientChunks,
389
+ }) as PluginOption,
390
+ );
406
391
  plugins.push(clientRefDedup());
407
392
  }
408
393
 
409
- // Fix HMR for "use client" components.
410
- //
411
- // @vitejs/plugin-rsc's hotUpdate returns undefined for "use client" files
412
- // in the RSC environment. Vite then tries to propagate through the RSC
413
- // module graph, but the proxy module has no import.meta.hot.accept()
414
- // boundary, causing a full page reload. The client env would handle it
415
- // fine via React Refresh, but the RSC env's full-reload arrives first.
416
- //
417
- // Fix: in the RSC env, return [] for "use client" files to signal
418
- // "handled, nothing to propagate". The client env is left alone so
419
- // React Refresh processes the update normally.
420
394
  plugins.push({
421
395
  name: "@rangojs/router:client-component-hmr",
422
396
  hotUpdate(ctx) {
@@ -435,76 +409,45 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
435
409
 
436
410
  try {
437
411
  const source = readFileSync(file, "utf-8");
438
- const trimmed = source.trimStart();
439
- if (
440
- trimmed.startsWith('"use client"') ||
441
- trimmed.startsWith("'use client'")
442
- ) {
443
- // Consume the update in RSC/SSR envs. The proxy module was already
444
- // re-transformed by the RSC plugin's hotUpdate. Without this, Vite
445
- // tries to propagate through the RSC/SSR module graph where the proxy
446
- // has no import.meta.hot.accept() boundary, triggering a full reload.
447
- // The actual component update is handled by React Refresh in the
448
- // client environment.
412
+ if (hasUseClientDirective(source)) {
449
413
  return [];
450
414
  }
451
- } catch {
452
- // File deleted/moved during HMR, let default handling proceed
453
- }
415
+ } catch {}
454
416
  },
455
417
  });
456
418
 
457
419
  plugins.push(exposeActionId());
458
-
459
- // "use cache" directive transform (enforce: "post"):
460
- // Wraps exports with registerCachedFunction() for function-level caching.
461
420
  plugins.push(useCacheTransform());
462
-
463
- // Consolidated plugin for create* ID injection (enforce: "post"):
464
- // loaders, handles, location state, and prerender handlers.
465
421
  plugins.push(exposeInternalIds());
466
-
467
- // Router ID injection runs at normal priority (no enforce) to avoid
468
- // changing Vite's dep optimization timing.
469
422
  plugins.push(exposeRouterId());
470
-
471
- // Add version virtual module plugin for cache invalidation
472
423
  plugins.push(createVersionPlugin());
473
424
 
474
- // Entry path for discovery: user-specified value (if any) or undefined.
475
- // Auto-discovered path is passed separately via routerRef.
476
- // Cloudflare preset: deferred to configResolved (read from resolved Vite env config).
477
425
  const discoveryEntryPath =
478
426
  preset !== "cloudflare" ? routerRef.path : undefined;
479
- // Ref for deferred auto-discovery (node preset only, undefined for cloudflare)
480
427
  const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
481
428
 
482
- // Version injector: auto-injects VERSION and routes-manifest into custom entry.rsc files.
483
- // Only applies when there's an explicit rscEntryPath or for cloudflare preset (resolved
484
- // lazily in configResolved). For node preset without a custom entry, the router file
485
- // must NOT be transformed — injecting routes-manifest there creates a circular dependency.
486
- const injectorEntryPath =
487
- rscEntryPath ?? (preset === "cloudflare" ? undefined : null);
488
- if (injectorEntryPath !== null) {
489
- plugins.push(createVersionInjectorPlugin(injectorEntryPath));
429
+ if (preset === "cloudflare") {
430
+ plugins.push(createVersionInjectorPlugin(undefined));
490
431
  }
491
432
 
492
- // Transform CJS vendor files to ESM for browser compatibility
493
- // optimizeDeps.include doesn't work because the file is loaded after initial optimization
494
433
  plugins.push(createCjsToEsmPlugin());
495
-
496
- // Router discovery plugin for build-time manifest generation.
497
- // For cloudflare, the entry is resolved lazily in configResolved from the RSC environment.
498
- // For node, discoveryRouterRef provides the auto-discovered path when not user-specified.
499
434
  plugins.push(
500
435
  createRouterDiscoveryPlugin(discoveryEntryPath, {
501
436
  routerPathRef: discoveryRouterRef,
502
437
  enableBuildPrerender: prerenderEnabled,
503
- staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration,
504
- include: resolvedOptions.include,
505
- exclude: resolvedOptions.exclude,
438
+ buildEnv: options?.buildEnv,
439
+ preset,
440
+ prerenderOnError: options?.prerender?.onError,
441
+ discovery: options?.discovery,
442
+ clientChunkCtx,
506
443
  }),
507
444
  );
508
445
 
446
+ debugConfig?.(
447
+ "rango(%s) setup done: %d plugin(s) (%sms)",
448
+ preset,
449
+ plugins.length,
450
+ (performance.now() - rangoStart).toFixed(1),
451
+ );
509
452
  return plugins;
510
453
  }