@depup/nitro 3.0.260311-beta-depup.0

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 (370) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +32 -0
  3. package/changes.json +14 -0
  4. package/dist/THIRD-PARTY-LICENSES.md +1646 -0
  5. package/dist/_build/common.mjs +29361 -0
  6. package/dist/_build/rolldown.mjs +173 -0
  7. package/dist/_build/rollup.mjs +194 -0
  8. package/dist/_build/vite.build.mjs +18 -0
  9. package/dist/_chunks/nitro.mjs +1159 -0
  10. package/dist/_chunks/nitro2.mjs +102 -0
  11. package/dist/_chunks/nitro3.mjs +129 -0
  12. package/dist/_chunks/utils.mjs +272 -0
  13. package/dist/_common.mjs +35 -0
  14. package/dist/_dev.d.mts +12 -0
  15. package/dist/_dev.mjs +519 -0
  16. package/dist/_libs/_.mjs +3 -0
  17. package/dist/_libs/_2.mjs +2 -0
  18. package/dist/_libs/_3.mjs +3 -0
  19. package/dist/_libs/_4.mjs +2 -0
  20. package/dist/_libs/_5.mjs +3 -0
  21. package/dist/_libs/_6.mjs +4 -0
  22. package/dist/_libs/_7.mjs +5 -0
  23. package/dist/_libs/c12+rc9.mjs +812 -0
  24. package/dist/_libs/c12+readdirp+chokidar.d.mts +230 -0
  25. package/dist/_libs/citty.mjs +361 -0
  26. package/dist/_libs/commondir+is-reference.mjs +1311 -0
  27. package/dist/_libs/compatx.d.mts +47 -0
  28. package/dist/_libs/compatx.mjs +45 -0
  29. package/dist/_libs/esbuild.d.mts +20 -0
  30. package/dist/_libs/escape-string-regexp.mjs +7 -0
  31. package/dist/_libs/estree+pluginutils.d.mts +241 -0
  32. package/dist/_libs/estree-walker.mjs +184 -0
  33. package/dist/_libs/exsolve.d.mts +1 -0
  34. package/dist/_libs/hasown+resolve+deepmerge.mjs +1949 -0
  35. package/dist/_libs/httpxy.d.mts +82 -0
  36. package/dist/_libs/httpxy.mjs +671 -0
  37. package/dist/_libs/js-tokens.d.mts +1 -0
  38. package/dist/_libs/klona.mjs +37 -0
  39. package/dist/_libs/magic-string.d.mts +220 -0
  40. package/dist/_libs/mlly.d.mts +57 -0
  41. package/dist/_libs/nypm+tinyexec.mjs +845 -0
  42. package/dist/_libs/perfect-debounce.mjs +88 -0
  43. package/dist/_libs/pkg-types.d.mts +23 -0
  44. package/dist/_libs/plugin-alias.mjs +64 -0
  45. package/dist/_libs/plugin-inject.mjs +131 -0
  46. package/dist/_libs/plugin-json.mjs +34 -0
  47. package/dist/_libs/pluginutils.mjs +646 -0
  48. package/dist/_libs/readdirp+chokidar.mjs +1606 -0
  49. package/dist/_libs/remapping.mjs +115 -0
  50. package/dist/_libs/resolve-uri+gen-mapping.mjs +442 -0
  51. package/dist/_libs/rou3.d.mts +44 -0
  52. package/dist/_libs/rou3.mjs +496 -0
  53. package/dist/_libs/std-env.d.mts +12 -0
  54. package/dist/_libs/strip-literal.d.mts +1 -0
  55. package/dist/_libs/tsconfck.mjs +813 -0
  56. package/dist/_libs/ultrahtml.mjs +127 -0
  57. package/dist/_libs/unimport+unplugin.mjs +1684 -0
  58. package/dist/_libs/unplugin+unimport.d.mts +423 -0
  59. package/dist/_libs/unwasm.d.mts +29 -0
  60. package/dist/_presets.mjs +1759 -0
  61. package/dist/builder.d.mts +64 -0
  62. package/dist/builder.mjs +15 -0
  63. package/dist/cli/_chunks/build.mjs +47 -0
  64. package/dist/cli/_chunks/common.mjs +14 -0
  65. package/dist/cli/_chunks/deploy.mjs +40 -0
  66. package/dist/cli/_chunks/dev.mjs +62 -0
  67. package/dist/cli/_chunks/docs.mjs +30 -0
  68. package/dist/cli/_chunks/list.mjs +25 -0
  69. package/dist/cli/_chunks/prepare.mjs +17 -0
  70. package/dist/cli/_chunks/preview.mjs +51 -0
  71. package/dist/cli/_chunks/run.mjs +53 -0
  72. package/dist/cli/_chunks/task.mjs +14 -0
  73. package/dist/cli/index.d.mts +1 -0
  74. package/dist/cli/index.mjs +22 -0
  75. package/dist/node_modules/@poppinss/colors/build/index.js +139 -0
  76. package/dist/node_modules/@poppinss/colors/package.json +118 -0
  77. package/dist/node_modules/@poppinss/dumper/build/chunk-26HALFTP.js +602 -0
  78. package/dist/node_modules/@poppinss/dumper/build/formatters/console/main.js +441 -0
  79. package/dist/node_modules/@poppinss/dumper/build/formatters/html/main.js +725 -0
  80. package/dist/node_modules/@poppinss/dumper/package.json +122 -0
  81. package/dist/node_modules/@poppinss/exception/build/index.js +44 -0
  82. package/dist/node_modules/@poppinss/exception/package.json +109 -0
  83. package/dist/node_modules/@sindresorhus/is/distribution/index.js +1354 -0
  84. package/dist/node_modules/@sindresorhus/is/distribution/utilities.js +3 -0
  85. package/dist/node_modules/@sindresorhus/is/package.json +81 -0
  86. package/dist/node_modules/@speed-highlight/core/dist/index.js +4 -0
  87. package/dist/node_modules/@speed-highlight/core/dist/terminal.js +2 -0
  88. package/dist/node_modules/@speed-highlight/core/package.json +94 -0
  89. package/dist/node_modules/cookie-es/dist/index.mjs +262 -0
  90. package/dist/node_modules/cookie-es/package.json +37 -0
  91. package/dist/node_modules/croner/dist/croner.js +1 -0
  92. package/dist/node_modules/croner/package.json +73 -0
  93. package/dist/node_modules/defu/dist/defu.mjs +69 -0
  94. package/dist/node_modules/defu/package.json +43 -0
  95. package/dist/node_modules/destr/dist/index.mjs +72 -0
  96. package/dist/node_modules/destr/package.json +47 -0
  97. package/dist/node_modules/error-stack-parser-es/dist/index.mjs +38 -0
  98. package/dist/node_modules/error-stack-parser-es/dist/lite.mjs +167 -0
  99. package/dist/node_modules/error-stack-parser-es/package.json +83 -0
  100. package/dist/node_modules/get-port-please/dist/index.mjs +430 -0
  101. package/dist/node_modules/get-port-please/package.json +39 -0
  102. package/dist/node_modules/kleur/index.mjs +110 -0
  103. package/dist/node_modules/kleur/package.json +51 -0
  104. package/dist/node_modules/rendu/dist/index.mjs +380 -0
  105. package/dist/node_modules/rendu/package.json +47 -0
  106. package/dist/node_modules/scule/dist/index.mjs +80 -0
  107. package/dist/node_modules/scule/package.json +43 -0
  108. package/dist/node_modules/source-map/lib/array-set.js +100 -0
  109. package/dist/node_modules/source-map/lib/base64-vlq.js +94 -0
  110. package/dist/node_modules/source-map/lib/base64.js +19 -0
  111. package/dist/node_modules/source-map/lib/binary-search.js +113 -0
  112. package/dist/node_modules/source-map/lib/mapping-list.js +83 -0
  113. package/dist/node_modules/source-map/lib/mappings.wasm +0 -0
  114. package/dist/node_modules/source-map/lib/read-wasm.js +27 -0
  115. package/dist/node_modules/source-map/lib/source-map-consumer.js +1081 -0
  116. package/dist/node_modules/source-map/lib/source-map-generator.js +439 -0
  117. package/dist/node_modules/source-map/lib/source-node.js +430 -0
  118. package/dist/node_modules/source-map/lib/url.js +13 -0
  119. package/dist/node_modules/source-map/lib/util.js +444 -0
  120. package/dist/node_modules/source-map/lib/wasm.js +138 -0
  121. package/dist/node_modules/source-map/package.json +79 -0
  122. package/dist/node_modules/source-map/source-map.js +10 -0
  123. package/dist/node_modules/supports-color/index.js +202 -0
  124. package/dist/node_modules/supports-color/package.json +64 -0
  125. package/dist/node_modules/ufo/dist/index.mjs +645 -0
  126. package/dist/node_modules/ufo/package.json +48 -0
  127. package/dist/node_modules/unctx/dist/index.mjs +131 -0
  128. package/dist/node_modules/unctx/package.json +67 -0
  129. package/dist/node_modules/youch/build/helpers-B9BQYaS6.js +23 -0
  130. package/dist/node_modules/youch/build/index.js +212 -0
  131. package/dist/node_modules/youch/build/public/error_cause/style.css +5 -0
  132. package/dist/node_modules/youch/build/public/error_info/script.js +13 -0
  133. package/dist/node_modules/youch/build/public/error_info/style.css +145 -0
  134. package/dist/node_modules/youch/build/public/error_metadata/style.css +3 -0
  135. package/dist/node_modules/youch/build/public/error_stack/script.js +72 -0
  136. package/dist/node_modules/youch/build/public/error_stack/style.css +219 -0
  137. package/dist/node_modules/youch/build/public/error_stack_source/style.css +123 -0
  138. package/dist/node_modules/youch/build/public/header/script.js +14 -0
  139. package/dist/node_modules/youch/build/public/header/style.css +56 -0
  140. package/dist/node_modules/youch/build/public/layout/script.js +12 -0
  141. package/dist/node_modules/youch/build/public/layout/style.css +435 -0
  142. package/dist/node_modules/youch/build/public_dir-C5bujZKB.js +25 -0
  143. package/dist/node_modules/youch/build/src/templates/error_cause/main.js +44 -0
  144. package/dist/node_modules/youch/build/src/templates/error_info/main.js +72 -0
  145. package/dist/node_modules/youch/build/src/templates/error_metadata/main.js +65 -0
  146. package/dist/node_modules/youch/build/src/templates/error_stack/main.js +152 -0
  147. package/dist/node_modules/youch/build/src/templates/error_stack_source/main.js +46 -0
  148. package/dist/node_modules/youch/build/src/templates/header/main.js +24 -0
  149. package/dist/node_modules/youch/build/src/templates/layout/main.js +27 -0
  150. package/dist/node_modules/youch/package.json +135 -0
  151. package/dist/node_modules/youch-core/build/index.js +316 -0
  152. package/dist/node_modules/youch-core/package.json +124 -0
  153. package/dist/presets/_nitro/runtime/nitro-dev.mjs +20 -0
  154. package/dist/presets/_nitro/runtime/nitro-prerenderer.mjs +15 -0
  155. package/dist/presets/_nitro/runtime/service-worker.mjs +23 -0
  156. package/dist/presets/aws-amplify/runtime/aws-amplify.mjs +14 -0
  157. package/dist/presets/aws-lambda/runtime/_utils.mjs +116 -0
  158. package/dist/presets/aws-lambda/runtime/aws-lambda-streaming.mjs +31 -0
  159. package/dist/presets/aws-lambda/runtime/aws-lambda.mjs +13 -0
  160. package/dist/presets/azure/runtime/_utils.mjs +50 -0
  161. package/dist/presets/azure/runtime/azure-swa.mjs +30 -0
  162. package/dist/presets/bun/runtime/bun.mjs +40 -0
  163. package/dist/presets/cloudflare/runtime/_module-handler.mjs +87 -0
  164. package/dist/presets/cloudflare/runtime/cloudflare-durable.mjs +72 -0
  165. package/dist/presets/cloudflare/runtime/cloudflare-module.mjs +17 -0
  166. package/dist/presets/cloudflare/runtime/cloudflare-pages.mjs +39 -0
  167. package/dist/presets/cloudflare/runtime/plugin.dev.mjs +96 -0
  168. package/dist/presets/cloudflare/runtime/shims/workers.dev.mjs +27 -0
  169. package/dist/presets/deno/runtime/deno-deploy.mjs +19 -0
  170. package/dist/presets/deno/runtime/deno-server.mjs +39 -0
  171. package/dist/presets/netlify/runtime/netlify-edge.mjs +20 -0
  172. package/dist/presets/netlify/runtime/netlify.mjs +20 -0
  173. package/dist/presets/node/runtime/node-cluster.mjs +54 -0
  174. package/dist/presets/node/runtime/node-middleware.mjs +14 -0
  175. package/dist/presets/node/runtime/node-server.mjs +47 -0
  176. package/dist/presets/standard/runtime/server.mjs +4 -0
  177. package/dist/presets/stormkit/runtime/stormkit.mjs +27 -0
  178. package/dist/presets/vercel/runtime/cron-handler.mjs +25 -0
  179. package/dist/presets/vercel/runtime/isr.mjs +19 -0
  180. package/dist/presets/vercel/runtime/vercel.node.mjs +24 -0
  181. package/dist/presets/vercel/runtime/vercel.web.mjs +23 -0
  182. package/dist/presets/winterjs/runtime/winterjs.mjs +91 -0
  183. package/dist/presets/zeabur/runtime/zeabur.mjs +4 -0
  184. package/dist/presets/zephyr/runtime/server.mjs +3 -0
  185. package/dist/runtime/app.d.mts +1 -0
  186. package/dist/runtime/app.mjs +1 -0
  187. package/dist/runtime/cache.d.mts +1 -0
  188. package/dist/runtime/cache.mjs +1 -0
  189. package/dist/runtime/config.d.mts +3 -0
  190. package/dist/runtime/config.mjs +4 -0
  191. package/dist/runtime/context.d.mts +1 -0
  192. package/dist/runtime/context.mjs +1 -0
  193. package/dist/runtime/database.d.mts +1 -0
  194. package/dist/runtime/database.mjs +1 -0
  195. package/dist/runtime/internal/app.d.mts +16 -0
  196. package/dist/runtime/internal/app.mjs +208 -0
  197. package/dist/runtime/internal/cache.d.mts +7 -0
  198. package/dist/runtime/internal/cache.mjs +41 -0
  199. package/dist/runtime/internal/context.d.mts +14 -0
  200. package/dist/runtime/internal/context.mjs +24 -0
  201. package/dist/runtime/internal/database.d.mts +2 -0
  202. package/dist/runtime/internal/database.mjs +12 -0
  203. package/dist/runtime/internal/empty.mjs +0 -0
  204. package/dist/runtime/internal/error/dev.d.mts +10 -0
  205. package/dist/runtime/internal/error/dev.mjs +121 -0
  206. package/dist/runtime/internal/error/hooks.d.mts +1 -0
  207. package/dist/runtime/internal/error/hooks.mjs +9 -0
  208. package/dist/runtime/internal/error/prod.d.mts +6 -0
  209. package/dist/runtime/internal/error/prod.mjs +40 -0
  210. package/dist/runtime/internal/error/utils.d.mts +8 -0
  211. package/dist/runtime/internal/error/utils.mjs +3 -0
  212. package/dist/runtime/internal/meta.d.mts +2 -0
  213. package/dist/runtime/internal/meta.mjs +3 -0
  214. package/dist/runtime/internal/plugin.d.mts +3 -0
  215. package/dist/runtime/internal/plugin.mjs +4 -0
  216. package/dist/runtime/internal/route-rules.d.mts +9 -0
  217. package/dist/runtime/internal/route-rules.mjs +72 -0
  218. package/dist/runtime/internal/routes/dev-tasks.d.mts +3 -0
  219. package/dist/runtime/internal/routes/dev-tasks.mjs +25 -0
  220. package/dist/runtime/internal/routes/openapi.d.mts +3 -0
  221. package/dist/runtime/internal/routes/openapi.mjs +94 -0
  222. package/dist/runtime/internal/routes/renderer-template.d.mts +2 -0
  223. package/dist/runtime/internal/routes/renderer-template.dev.d.mts +3 -0
  224. package/dist/runtime/internal/routes/renderer-template.dev.mjs +19 -0
  225. package/dist/runtime/internal/routes/renderer-template.mjs +4 -0
  226. package/dist/runtime/internal/routes/scalar.d.mts +3 -0
  227. package/dist/runtime/internal/routes/scalar.mjs +193 -0
  228. package/dist/runtime/internal/routes/swagger.d.mts +3 -0
  229. package/dist/runtime/internal/routes/swagger.mjs +42 -0
  230. package/dist/runtime/internal/runtime-config.d.mts +9 -0
  231. package/dist/runtime/internal/runtime-config.mjs +54 -0
  232. package/dist/runtime/internal/static.d.mts +3 -0
  233. package/dist/runtime/internal/static.mjs +67 -0
  234. package/dist/runtime/internal/storage.d.mts +2 -0
  235. package/dist/runtime/internal/storage.mjs +6 -0
  236. package/dist/runtime/internal/task.d.mts +19 -0
  237. package/dist/runtime/internal/task.mjs +69 -0
  238. package/dist/runtime/internal/vite/dev-entry.mjs +18 -0
  239. package/dist/runtime/internal/vite/dev-worker.mjs +264 -0
  240. package/dist/runtime/internal/vite/ssr-renderer.mjs +6 -0
  241. package/dist/runtime/meta.d.mts +5 -0
  242. package/dist/runtime/meta.mjs +27 -0
  243. package/dist/runtime/nitro.d.mts +11 -0
  244. package/dist/runtime/nitro.mjs +34 -0
  245. package/dist/runtime/runtime-config.d.mts +1 -0
  246. package/dist/runtime/runtime-config.mjs +1 -0
  247. package/dist/runtime/storage.d.mts +1 -0
  248. package/dist/runtime/storage.mjs +1 -0
  249. package/dist/runtime/task.d.mts +1 -0
  250. package/dist/runtime/task.mjs +1 -0
  251. package/dist/runtime/virtual/_runtime_warn.d.mts +1 -0
  252. package/dist/runtime/virtual/_runtime_warn.mjs +5 -0
  253. package/dist/runtime/virtual/database.d.mts +8 -0
  254. package/dist/runtime/virtual/database.mjs +2 -0
  255. package/dist/runtime/virtual/error-handler.d.mts +6 -0
  256. package/dist/runtime/virtual/error-handler.mjs +9 -0
  257. package/dist/runtime/virtual/feature-flags.d.mts +7 -0
  258. package/dist/runtime/virtual/feature-flags.mjs +7 -0
  259. package/dist/runtime/virtual/plugins.d.mts +3 -0
  260. package/dist/runtime/virtual/plugins.mjs +2 -0
  261. package/dist/runtime/virtual/polyfills.d.mts +3 -0
  262. package/dist/runtime/virtual/polyfills.mjs +2 -0
  263. package/dist/runtime/virtual/public-assets.d.mts +9 -0
  264. package/dist/runtime/virtual/public-assets.mjs +8 -0
  265. package/dist/runtime/virtual/renderer-template.d.mts +4 -0
  266. package/dist/runtime/virtual/renderer-template.mjs +7 -0
  267. package/dist/runtime/virtual/routing-meta.d.mts +7 -0
  268. package/dist/runtime/virtual/routing-meta.mjs +2 -0
  269. package/dist/runtime/virtual/routing.d.mts +8 -0
  270. package/dist/runtime/virtual/routing.mjs +11 -0
  271. package/dist/runtime/virtual/runtime-config.d.mts +3 -0
  272. package/dist/runtime/virtual/runtime-config.mjs +5 -0
  273. package/dist/runtime/virtual/server-assets.d.mts +7 -0
  274. package/dist/runtime/virtual/server-assets.mjs +12 -0
  275. package/dist/runtime/virtual/storage.d.mts +3 -0
  276. package/dist/runtime/virtual/storage.mjs +5 -0
  277. package/dist/runtime/virtual/tasks.d.mts +10 -0
  278. package/dist/runtime/virtual/tasks.mjs +3 -0
  279. package/dist/runtime/vite.d.mts +8 -0
  280. package/dist/runtime/vite.mjs +9 -0
  281. package/dist/types/index.d.mts +3010 -0
  282. package/dist/types/index.mjs +1 -0
  283. package/dist/vite.d.mts +52 -0
  284. package/dist/vite.mjs +740 -0
  285. package/lib/h3.d.mts +1 -0
  286. package/lib/h3.mjs +1 -0
  287. package/lib/tsconfig.json +27 -0
  288. package/lib/vite.types.d.mts +26 -0
  289. package/lib/vite.types.mjs +2 -0
  290. package/package.json +256 -0
  291. package/skills/nitro/SKILL.md +10 -0
  292. package/skills/nitro/docs/TOC.md +83 -0
  293. package/skills/nitro/docs/_navigation.json +679 -0
  294. package/skills/nitro/docs/config/index.md +1147 -0
  295. package/skills/nitro/docs/deploy/index.md +64 -0
  296. package/skills/nitro/docs/deploy/providers/alwaysdata.md +50 -0
  297. package/skills/nitro/docs/deploy/providers/aws-amplify.md +81 -0
  298. package/skills/nitro/docs/deploy/providers/aws.md +47 -0
  299. package/skills/nitro/docs/deploy/providers/azure.md +72 -0
  300. package/skills/nitro/docs/deploy/providers/cleavr.md +33 -0
  301. package/skills/nitro/docs/deploy/providers/cloudflare.md +375 -0
  302. package/skills/nitro/docs/deploy/providers/deno-deploy.md +66 -0
  303. package/skills/nitro/docs/deploy/providers/digitalocean.md +46 -0
  304. package/skills/nitro/docs/deploy/providers/firebase.md +32 -0
  305. package/skills/nitro/docs/deploy/providers/flightcontrol.md +67 -0
  306. package/skills/nitro/docs/deploy/providers/genezio.md +67 -0
  307. package/skills/nitro/docs/deploy/providers/github-pages.md +68 -0
  308. package/skills/nitro/docs/deploy/providers/gitlab-pages.md +37 -0
  309. package/skills/nitro/docs/deploy/providers/heroku.md +84 -0
  310. package/skills/nitro/docs/deploy/providers/iis.md +38 -0
  311. package/skills/nitro/docs/deploy/providers/koyeb.md +109 -0
  312. package/skills/nitro/docs/deploy/providers/netlify.md +47 -0
  313. package/skills/nitro/docs/deploy/providers/platform-sh.md +37 -0
  314. package/skills/nitro/docs/deploy/providers/render.md +37 -0
  315. package/skills/nitro/docs/deploy/providers/stormkit.md +24 -0
  316. package/skills/nitro/docs/deploy/providers/vercel.md +179 -0
  317. package/skills/nitro/docs/deploy/providers/zeabur.md +19 -0
  318. package/skills/nitro/docs/deploy/providers/zephyr.md +99 -0
  319. package/skills/nitro/docs/deploy/providers/zerops.md +102 -0
  320. package/skills/nitro/docs/deploy/runtimes/bun.md +15 -0
  321. package/skills/nitro/docs/deploy/runtimes/deno.md +19 -0
  322. package/skills/nitro/docs/deploy/runtimes/node.md +63 -0
  323. package/skills/nitro/docs/docs/assets.md +166 -0
  324. package/skills/nitro/docs/docs/cache.md +408 -0
  325. package/skills/nitro/docs/docs/configuration.md +256 -0
  326. package/skills/nitro/docs/docs/database.md +185 -0
  327. package/skills/nitro/docs/docs/index.md +56 -0
  328. package/skills/nitro/docs/docs/lifecycle.md +204 -0
  329. package/skills/nitro/docs/docs/migration.md +215 -0
  330. package/skills/nitro/docs/docs/nightly.md +31 -0
  331. package/skills/nitro/docs/docs/plugins.md +164 -0
  332. package/skills/nitro/docs/docs/quick-start.md +110 -0
  333. package/skills/nitro/docs/docs/renderer.md +322 -0
  334. package/skills/nitro/docs/docs/routing.md +711 -0
  335. package/skills/nitro/docs/docs/server-entry.md +239 -0
  336. package/skills/nitro/docs/docs/storage.md +261 -0
  337. package/skills/nitro/docs/docs/tasks.md +277 -0
  338. package/skills/nitro/docs/examples/api-routes.md +145 -0
  339. package/skills/nitro/docs/examples/auto-imports.md +93 -0
  340. package/skills/nitro/docs/examples/cached-handler.md +81 -0
  341. package/skills/nitro/docs/examples/custom-error-handler.md +98 -0
  342. package/skills/nitro/docs/examples/database.md +157 -0
  343. package/skills/nitro/docs/examples/elysia.md +70 -0
  344. package/skills/nitro/docs/examples/express.md +78 -0
  345. package/skills/nitro/docs/examples/fastify.md +79 -0
  346. package/skills/nitro/docs/examples/hello-world.md +68 -0
  347. package/skills/nitro/docs/examples/hono.md +74 -0
  348. package/skills/nitro/docs/examples/import-alias.md +100 -0
  349. package/skills/nitro/docs/examples/index.md +3 -0
  350. package/skills/nitro/docs/examples/middleware.md +91 -0
  351. package/skills/nitro/docs/examples/mono-jsx.md +68 -0
  352. package/skills/nitro/docs/examples/nano-jsx.md +70 -0
  353. package/skills/nitro/docs/examples/plugins.md +91 -0
  354. package/skills/nitro/docs/examples/renderer.md +113 -0
  355. package/skills/nitro/docs/examples/runtime-config.md +97 -0
  356. package/skills/nitro/docs/examples/server-fetch.md +87 -0
  357. package/skills/nitro/docs/examples/shiki.md +198 -0
  358. package/skills/nitro/docs/examples/virtual-routes.md +74 -0
  359. package/skills/nitro/docs/examples/vite-nitro-plugin.md +79 -0
  360. package/skills/nitro/docs/examples/vite-rsc.md +1041 -0
  361. package/skills/nitro/docs/examples/vite-ssr-html.md +217 -0
  362. package/skills/nitro/docs/examples/vite-ssr-preact.md +247 -0
  363. package/skills/nitro/docs/examples/vite-ssr-react.md +226 -0
  364. package/skills/nitro/docs/examples/vite-ssr-solid.md +256 -0
  365. package/skills/nitro/docs/examples/vite-ssr-tsr-react.md +442 -0
  366. package/skills/nitro/docs/examples/vite-ssr-tss-react.md +444 -0
  367. package/skills/nitro/docs/examples/vite-ssr-vue-router.md +616 -0
  368. package/skills/nitro/docs/examples/vite-trpc.md +335 -0
  369. package/skills/nitro/docs/examples/websocket.md +282 -0
  370. package/skills/nitro/docs/index.md +121 -0
@@ -0,0 +1,1041 @@
1
+ # Vite RSC
2
+
3
+ > React Server Components with Vite and Nitro.
4
+
5
+ <code-tree>
6
+
7
+ ```json [package.json]
8
+ {
9
+ "name": "@vitejs/plugin-rsc-examples-starter",
10
+ "version": "0.0.0",
11
+ "private": true,
12
+ "license": "MIT",
13
+ "type": "module",
14
+ "scripts": {
15
+ "dev": "vite",
16
+ "build": "vite build",
17
+ "preview": "vite preview"
18
+ },
19
+ "dependencies": {
20
+ "react": "^19.2.4",
21
+ "react-dom": "^19.2.4"
22
+ },
23
+ "devDependencies": {
24
+ "@types/react": "^19.2.13",
25
+ "@types/react-dom": "^19.2.3",
26
+ "@vitejs/plugin-react": "^5.1.3",
27
+ "@vitejs/plugin-rsc": "^0.5.19",
28
+ "nitro": "latest",
29
+ "rsc-html-stream": "^0.0.7",
30
+ "vite": "beta"
31
+ }
32
+ }
33
+ ```
34
+
35
+ ```json [tsconfig.json]
36
+ {
37
+ "extends": "nitro/tsconfig",
38
+ "compilerOptions": {
39
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
40
+ "types": ["vite/client", "@vitejs/plugin-rsc/types"],
41
+ "jsx": "react-jsx"
42
+ }
43
+ }
44
+ ```
45
+
46
+ ```ts [vite.config.ts]
47
+ import { defineConfig } from "vite";
48
+ import { nitro } from "nitro/vite";
49
+
50
+ import rsc from "@vitejs/plugin-rsc";
51
+ import react from "@vitejs/plugin-react";
52
+
53
+ export default defineConfig({
54
+ plugins: [
55
+ nitro(),
56
+ rsc({
57
+ serverHandler: false,
58
+ entries: {
59
+ ssr: "./app/framework/entry.ssr.tsx",
60
+ rsc: "./app/framework/entry.rsc.tsx",
61
+ },
62
+ }),
63
+ react(),
64
+ ],
65
+
66
+ environments: {
67
+ client: {
68
+ build: {
69
+ rollupOptions: {
70
+ input: { index: "./app/framework/entry.browser.tsx" },
71
+ },
72
+ },
73
+ },
74
+ },
75
+ });
76
+ ```
77
+
78
+ ```tsx [app/action.tsx]
79
+ "use server";
80
+
81
+ let serverCounter = 0;
82
+
83
+ export async function getServerCounter() {
84
+ return serverCounter;
85
+ }
86
+
87
+ export async function updateServerCounter(change: number) {
88
+ serverCounter += change;
89
+ }
90
+ ```
91
+
92
+ ```tsx [app/client.tsx]
93
+ "use client";
94
+
95
+ import React from "react";
96
+
97
+ export function ClientCounter() {
98
+ const [count, setCount] = React.useState(0);
99
+
100
+ return <button onClick={() => setCount((count) => count + 1)}>Client Counter: {count}</button>;
101
+ }
102
+ ```
103
+
104
+ ```css [app/index.css]
105
+ :root {
106
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
107
+ line-height: 1.5;
108
+ font-weight: 400;
109
+
110
+ color-scheme: light dark;
111
+ color: rgba(255, 255, 255, 0.87);
112
+ background-color: #242424;
113
+
114
+ font-synthesis: none;
115
+ text-rendering: optimizeLegibility;
116
+ -webkit-font-smoothing: antialiased;
117
+ -moz-osx-font-smoothing: grayscale;
118
+ }
119
+
120
+ a {
121
+ font-weight: 500;
122
+ color: #646cff;
123
+ text-decoration: inherit;
124
+ }
125
+ a:hover {
126
+ color: #535bf2;
127
+ }
128
+
129
+ body {
130
+ margin: 0;
131
+ display: flex;
132
+ place-items: center;
133
+ min-width: 320px;
134
+ min-height: 100vh;
135
+ }
136
+
137
+ h1 {
138
+ font-size: 3.2em;
139
+ line-height: 1.1;
140
+ }
141
+
142
+ button {
143
+ border-radius: 8px;
144
+ border: 1px solid transparent;
145
+ padding: 0.6em 1.2em;
146
+ font-size: 1em;
147
+ font-weight: 500;
148
+ font-family: inherit;
149
+ background-color: #1a1a1a;
150
+ cursor: pointer;
151
+ transition: border-color 0.25s;
152
+ }
153
+ button:hover {
154
+ border-color: #646cff;
155
+ }
156
+ button:focus,
157
+ button:focus-visible {
158
+ outline: 4px auto -webkit-focus-ring-color;
159
+ }
160
+
161
+ @media (prefers-color-scheme: light) {
162
+ :root {
163
+ color: #213547;
164
+ background-color: #ffffff;
165
+ }
166
+ a:hover {
167
+ color: #747bff;
168
+ }
169
+ button {
170
+ background-color: #f9f9f9;
171
+ }
172
+ }
173
+
174
+ #root {
175
+ max-width: 1280px;
176
+ margin: 0 auto;
177
+ padding: 2rem;
178
+ text-align: center;
179
+ }
180
+
181
+ .logo {
182
+ height: 6em;
183
+ padding: 1.5em;
184
+ will-change: filter;
185
+ transition: filter 300ms;
186
+ }
187
+ .logo:hover {
188
+ filter: drop-shadow(0 0 2em #646cffaa);
189
+ }
190
+ .logo.react:hover {
191
+ filter: drop-shadow(0 0 2em #61dafbaa);
192
+ }
193
+
194
+ @keyframes logo-spin {
195
+ from {
196
+ transform: rotate(0deg);
197
+ }
198
+ to {
199
+ transform: rotate(360deg);
200
+ }
201
+ }
202
+
203
+ @media (prefers-reduced-motion: no-preference) {
204
+ a:nth-of-type(2) .logo {
205
+ animation: logo-spin infinite 20s linear;
206
+ }
207
+ }
208
+
209
+ .card {
210
+ padding: 1rem;
211
+ }
212
+
213
+ .read-the-docs {
214
+ color: #888;
215
+ text-align: left;
216
+ }
217
+ ```
218
+
219
+ ```tsx [app/root.tsx]
220
+ import "./index.css"; // css import is automatically injected in exported server components
221
+ import viteLogo from "./assets/vite.svg";
222
+ import { getServerCounter, updateServerCounter } from "./action.tsx";
223
+ import reactLogo from "./assets/react.svg";
224
+ import nitroLogo from "./assets/nitro.svg";
225
+ import { ClientCounter } from "./client.tsx";
226
+
227
+ export function Root(props: { url: URL }) {
228
+ return (
229
+ <html lang="en">
230
+ <head>
231
+ {/* eslint-disable-next-line unicorn/text-encoding-identifier-case */}
232
+ <meta charSet="UTF-8" />
233
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
234
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
235
+ <title>Nitro + Vite + RSC</title>
236
+ </head>
237
+ <body>
238
+ <App {...props} />
239
+ </body>
240
+ </html>
241
+ );
242
+ }
243
+
244
+ function App(props: { url: URL }) {
245
+ return (
246
+ <div id="root">
247
+ <div>
248
+ <a href="https://vite.dev" target="_blank">
249
+ <img src={viteLogo} className="logo" alt="Vite logo" />
250
+ </a>
251
+ <a href="https://react.dev/reference/rsc/server-components" target="_blank">
252
+ <img src={reactLogo} className="logo react" alt="React logo" />
253
+ </a>
254
+
255
+ <a href="https://nitro.build" target="_blank">
256
+ <img src={nitroLogo} className="logo" alt="Nitro logo" />
257
+ </a>
258
+ </div>
259
+ <h1>Vite + RSC + Nitro</h1>
260
+ <div className="card">
261
+ <ClientCounter />
262
+ </div>
263
+ <div className="card">
264
+ <form action={updateServerCounter.bind(null, 1)}>
265
+ <button>Server Counter: {getServerCounter()}</button>
266
+ </form>
267
+ </div>
268
+ <div className="card">Request URL: {props.url?.href}</div>
269
+ <ul className="read-the-docs">
270
+ <li>
271
+ Edit <code>src/client.tsx</code> to test client HMR.
272
+ </li>
273
+ <li>
274
+ Edit <code>src/root.tsx</code> to test server HMR.
275
+ </li>
276
+ <li>
277
+ Visit{" "}
278
+ <a href="./_.rsc" target="_blank">
279
+ <code>_.rsc</code>
280
+ </a>{" "}
281
+ to view RSC stream payload.
282
+ </li>
283
+ <li>
284
+ Visit{" "}
285
+ <a href="?__nojs" target="_blank">
286
+ <code>?__nojs</code>
287
+ </a>{" "}
288
+ to test server action without js enabled.
289
+ </li>
290
+ </ul>
291
+ </div>
292
+ );
293
+ }
294
+ ```
295
+
296
+ ```text [app/assets/nitro.svg]
297
+ <!-- nitro logo -->
298
+ <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
299
+ <g clip-path="url(#clip0_115_108)">
300
+ <path fill-rule="evenodd" clip-rule="evenodd"
301
+ d="M35.2166 7.02016C28.0478 -1.38317 15.4241 -2.38397 7.02077 4.78481C-1.38256 11.9536 -2.38336 24.5773 4.78542 32.9806C11.9542 41.3839 24.5779 42.3847 32.9812 35.216C41.3846 28.0472 42.3854 15.4235 35.2166 7.02016ZM25.2525 17.5175C26.0233 17.5175 26.5155 18.3527 26.1287 19.0194L26.0175 19.2111L18.4696 31.6294C18.3293 31.8602 18.0788 32.001 17.8088 32.001H17.0883C16.5946 32.001 16.2336 31.5349 16.3573 31.0569L18.4054 23.1384C18.5691 22.5053 18.0912 21.888 17.4373 21.888H14.2914C13.6375 21.888 13.1596 21.2708 13.3232 20.6377L16.4137 8.68289C16.5261 8.28056 16.8904 7.99734 17.3081 8.00208C17.3587 8.00266 17.4046 8.0035 17.4427 8.0047L20.6109 8.00465C21.217 8.00436 21.684 8.53896 21.6023 9.13949L21.5828 9.28246L20.3746 16.349C20.2702 16.9598 20.7406 17.5175 21.3603 17.5175H25.2525Z"
302
+ fill="url(#paint0_diamond_115_108)" />
303
+ <mask id="mask0_115_108" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0"
304
+ width="40" height="41">
305
+ <circle cx="20" cy="20.001" r="20" fill="url(#paint1_diamond_115_108)" />
306
+ </mask>
307
+ <g mask="url(#mask0_115_108)">
308
+ <g filter="url(#filter0_f_115_108)">
309
+ <path
310
+ d="M1.11145 13.4267C0.0703174 16.4179 -0.245523 19.6136 0.189923 22.7507C0.62537 25.8879 1.79965 28.8768 3.61611 31.4713C5.43256 34.0659 7.83925 36.192 10.6381 37.6746C13.4369 39.1572 16.5478 39.9538 19.7147 39.999C22.8816 40.0442 26.0139 39.3366 28.8539 37.9345C31.6939 36.5324 34.1602 34.4758 36.05 31.9341C37.9397 29.3924 39.1988 26.4383 39.7236 23.3148C40.2483 20.1914 40.0238 16.9879 39.0684 13.9682L33.2532 15.808C33.9172 17.9068 34.0732 20.1333 33.7085 22.3042C33.3438 24.4751 32.4687 26.5283 31.1552 28.2949C29.8418 30.0615 28.1276 31.4908 26.1537 32.4653C24.1799 33.4399 22.0028 33.9316 19.8017 33.9002C17.6006 33.8688 15.4384 33.3151 13.4932 32.2847C11.5479 31.2543 9.87518 29.7766 8.61269 27.9733C7.35019 26.1699 6.53403 24.0926 6.23138 21.9122C5.92873 19.7317 6.14825 17.5106 6.87187 15.4316L1.11145 13.4267Z"
311
+ fill="white" />
312
+ </g>
313
+ </g>
314
+ </g>
315
+ <defs>
316
+ <filter id="filter0_f_115_108" x="-10" y="3.42667" width="60" height="46.5744"
317
+ filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
318
+ <feFlood flood-opacity="0" result="BackgroundImageFix" />
319
+ <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
320
+ <feGaussianBlur stdDeviation="5" result="effect1_foregroundBlur_115_108" />
321
+ </filter>
322
+ <radialGradient id="paint0_diamond_115_108" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
323
+ gradientTransform="translate(4.00069 20.0004) scale(39.0007 397.71)">
324
+ <stop stop-color="#31B2F3" />
325
+ <stop offset="0.473958" stop-color="#F27CEC" />
326
+ <stop offset="1" stop-color="#FD6641" />
327
+ </radialGradient>
328
+ <radialGradient id="paint1_diamond_115_108" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
329
+ gradientTransform="translate(4 20.0011) scale(39 397.703)">
330
+ <stop stop-color="#F27CEC" />
331
+ <stop offset="0.484375" stop-color="#31B2F3" />
332
+ <stop offset="1" stop-color="#7D7573" />
333
+ </radialGradient>
334
+ <clipPath id="clip0_115_108">
335
+ <rect width="146" height="40.001" fill="white" />
336
+ </clipPath>
337
+ </defs>
338
+ </svg>
339
+ ```
340
+
341
+ ```text [app/assets/react.svg]
342
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
343
+ ```
344
+
345
+ ```text [app/assets/vite.svg]
346
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
347
+ ```
348
+
349
+ ```tsx [app/framework/entry.browser.tsx]
350
+ import {
351
+ createFromReadableStream,
352
+ createFromFetch,
353
+ setServerCallback,
354
+ createTemporaryReferenceSet,
355
+ encodeReply,
356
+ } from "@vitejs/plugin-rsc/browser";
357
+ import React from "react";
358
+ import { createRoot, hydrateRoot } from "react-dom/client";
359
+ import { rscStream } from "rsc-html-stream/client";
360
+ import { GlobalErrorBoundary } from "./error-boundary";
361
+ import type { RscPayload } from "./entry.rsc";
362
+ import { createRscRenderRequest } from "./request";
363
+
364
+ async function main() {
365
+ // Stash `setPayload` function to trigger re-rendering
366
+ // from outside of `BrowserRoot` component (e.g. server function call, navigation, hmr)
367
+ let setPayload: (v: RscPayload) => void;
368
+
369
+ // Deserialize RSC stream back to React VDOM for CSR
370
+ const initialPayload = await createFromReadableStream<RscPayload>(
371
+ // Initial RSC stream is injected in SSR stream as <script>...FLIGHT_DATA...</script>
372
+ rscStream
373
+ );
374
+
375
+ // Browser root component to (re-)render RSC payload as state
376
+ function BrowserRoot() {
377
+ const [payload, setPayload_] = React.useState(initialPayload);
378
+
379
+ React.useEffect(() => {
380
+ setPayload = (v) => React.startTransition(() => setPayload_(v));
381
+ }, [setPayload_]);
382
+
383
+ // Re-fetch/render on client side navigation
384
+ React.useEffect(() => {
385
+ return listenNavigation(() => fetchRscPayload());
386
+ }, []);
387
+
388
+ return payload.root;
389
+ }
390
+
391
+ // Re-fetch RSC and trigger re-rendering
392
+ async function fetchRscPayload() {
393
+ const renderRequest = createRscRenderRequest(globalThis.location.href);
394
+ const payload = await createFromFetch<RscPayload>(fetch(renderRequest));
395
+ setPayload(payload);
396
+ }
397
+
398
+ // Register a handler which will be internally called by React
399
+ // on server function request after hydration.
400
+ setServerCallback(async (id, args) => {
401
+ const temporaryReferences = createTemporaryReferenceSet();
402
+ const renderRequest = createRscRenderRequest(globalThis.location.href, {
403
+ id,
404
+ body: await encodeReply(args, { temporaryReferences }),
405
+ });
406
+ const payload = await createFromFetch<RscPayload>(fetch(renderRequest), {
407
+ temporaryReferences,
408
+ });
409
+ setPayload(payload);
410
+ const { ok, data } = payload.returnValue!;
411
+ if (!ok) throw data;
412
+ return data;
413
+ });
414
+
415
+ // Hydration
416
+ const browserRoot = (
417
+ <React.StrictMode>
418
+ <GlobalErrorBoundary>
419
+ <BrowserRoot />
420
+ </GlobalErrorBoundary>
421
+ </React.StrictMode>
422
+ );
423
+ if ("__NO_HYDRATE" in globalThis) {
424
+ createRoot(document).render(browserRoot);
425
+ } else {
426
+ hydrateRoot(document, browserRoot, {
427
+ formState: initialPayload.formState,
428
+ });
429
+ }
430
+
431
+ // Implement server HMR by triggering re-fetch/render of RSC upon server code change
432
+ if (import.meta.hot) {
433
+ import.meta.hot.on("rsc:update", () => {
434
+ fetchRscPayload();
435
+ });
436
+ }
437
+ }
438
+
439
+ // A little helper to setup events interception for client side navigation
440
+ function listenNavigation(onNavigation: () => void) {
441
+ globalThis.addEventListener("popstate", onNavigation);
442
+
443
+ const oldPushState = globalThis.history.pushState;
444
+ globalThis.history.pushState = function (...args) {
445
+ const res = oldPushState.apply(this, args);
446
+ onNavigation();
447
+ return res;
448
+ };
449
+
450
+ const oldReplaceState = globalThis.history.replaceState;
451
+ globalThis.history.replaceState = function (...args) {
452
+ const res = oldReplaceState.apply(this, args);
453
+ onNavigation();
454
+ return res;
455
+ };
456
+
457
+ function onClick(e: MouseEvent) {
458
+ const link = (e.target as Element).closest("a");
459
+ if (
460
+ link &&
461
+ link instanceof HTMLAnchorElement &&
462
+ link.href &&
463
+ (!link.target || link.target === "_self") &&
464
+ link.origin === location.origin &&
465
+ !link.hasAttribute("download") &&
466
+ e.button === 0 && // left clicks only
467
+ !e.metaKey && // open in new tab (mac)
468
+ !e.ctrlKey && // open in new tab (windows)
469
+ !e.altKey && // download
470
+ !e.shiftKey &&
471
+ !e.defaultPrevented
472
+ ) {
473
+ e.preventDefault();
474
+ history.pushState(null, "", link.href);
475
+ }
476
+ }
477
+ document.addEventListener("click", onClick);
478
+
479
+ return () => {
480
+ document.removeEventListener("click", onClick);
481
+ globalThis.removeEventListener("popstate", onNavigation);
482
+ globalThis.history.pushState = oldPushState;
483
+ globalThis.history.replaceState = oldReplaceState;
484
+ };
485
+ }
486
+
487
+ // eslint-disable-next-line unicorn/prefer-top-level-await
488
+ main();
489
+ ```
490
+
491
+ ```tsx [app/framework/entry.rsc.tsx]
492
+ import {
493
+ renderToReadableStream,
494
+ createTemporaryReferenceSet,
495
+ decodeReply,
496
+ loadServerAction,
497
+ decodeAction,
498
+ decodeFormState,
499
+ } from "@vitejs/plugin-rsc/rsc";
500
+ import type { ReactFormState } from "react-dom/client";
501
+ import { Root } from "../root.tsx";
502
+ import { parseRenderRequest } from "./request.tsx";
503
+
504
+ // The schema of payload which is serialized into RSC stream on rsc environment
505
+ // and deserialized on ssr/client environments.
506
+ export type RscPayload = {
507
+ // this demo renders/serializes/deserializes entire root html element
508
+ // but this mechanism can be changed to render/fetch different parts of components
509
+ // based on your own route conventions.
510
+ root: React.ReactNode;
511
+
512
+ // Server action return value of non-progressive enhancement case
513
+ returnValue?: { ok: boolean; data: unknown };
514
+
515
+ // Server action form state (e.g. useActionState) of progressive enhancement case
516
+ formState?: ReactFormState;
517
+ };
518
+
519
+ // The plugin by default assumes `rsc` entry having default export of request handler.
520
+ // however, how server entries are executed can be customized by registering own server handler.
521
+ export default async function handler(request: Request): Promise<Response> {
522
+ // Differentiate RSC, SSR, action, etc.
523
+ const renderRequest = parseRenderRequest(request);
524
+ request = renderRequest.request;
525
+
526
+ // Handle server function request
527
+ let returnValue: RscPayload["returnValue"] | undefined;
528
+ let formState: ReactFormState | undefined;
529
+ let temporaryReferences: unknown | undefined;
530
+ let actionStatus: number | undefined;
531
+
532
+ if (renderRequest.isAction === true) {
533
+ if (renderRequest.actionId) {
534
+ // Action is called via `ReactClient.setServerCallback`.
535
+ const contentType = request.headers.get("content-type");
536
+ const body = contentType?.startsWith("multipart/form-data")
537
+ ? await request.formData()
538
+ : await request.text();
539
+ temporaryReferences = createTemporaryReferenceSet();
540
+ const args = await decodeReply(body, { temporaryReferences });
541
+ const action = await loadServerAction(renderRequest.actionId);
542
+ try {
543
+ // eslint-disable-next-line prefer-spread
544
+ const data = await action.apply(null, args);
545
+ returnValue = { ok: true, data };
546
+ } catch (error_) {
547
+ returnValue = { ok: false, data: error_ };
548
+ actionStatus = 500;
549
+ }
550
+ } else {
551
+ // Otherwise server function is called via `<form action={...}>`
552
+ // before hydration (e.g. when JavaScript is disabled).
553
+ // aka progressive enhancement.
554
+ const formData = await request.formData();
555
+ const decodedAction = await decodeAction(formData);
556
+ try {
557
+ const result = await decodedAction();
558
+ formState = await decodeFormState(result, formData);
559
+ } catch {
560
+ // there's no single general obvious way to surface this error,
561
+ // so explicitly return classic 500 response.
562
+ return new Response("Internal Server Error: server action failed", {
563
+ status: 500,
564
+ });
565
+ }
566
+ }
567
+ }
568
+
569
+ // Serialization from React VDOM tree to RSC stream.
570
+ // We render RSC stream after handling server function request
571
+ // so that new render reflects updated state from server function call
572
+ // to achieve single round trip to mutate and fetch from server.
573
+ const rscPayload: RscPayload = {
574
+ root: <Root url={renderRequest.url} />,
575
+ formState,
576
+ returnValue,
577
+ };
578
+
579
+ const rscOptions = { temporaryReferences };
580
+ const rscStream = renderToReadableStream<RscPayload>(rscPayload, rscOptions);
581
+
582
+ // Respond RSC stream without HTML rendering as decided by `RenderRequest`
583
+ if (renderRequest.isRsc) {
584
+ return new Response(rscStream, {
585
+ status: actionStatus,
586
+ headers: {
587
+ "content-type": "text/x-component;charset=utf-8",
588
+ },
589
+ });
590
+ }
591
+
592
+ // Delegate to SSR environment for HTML rendering.
593
+ // The plugin provides `loadModule` helper to allow loading SSR environment entry module
594
+ // in RSC environment. however this can be customized by implementing own runtime communication
595
+ // e.g. `@cloudflare/vite-plugin`'s service binding.
596
+ const ssrEntryModule = await import.meta.viteRsc.loadModule<typeof import("./entry.ssr.tsx")>(
597
+ "ssr",
598
+ "index"
599
+ );
600
+
601
+ const ssrResult = await ssrEntryModule.renderHTML(rscStream, {
602
+ formState,
603
+ // Allow quick simulation of JavaScript disabled browser
604
+ debugNoJS: renderRequest.url.searchParams.has("__nojs"),
605
+ });
606
+
607
+ // Respond HTML
608
+ return new Response(ssrResult.stream, {
609
+ status: ssrResult.status,
610
+ headers: {
611
+ "Content-Type": "text/html",
612
+ },
613
+ });
614
+ }
615
+
616
+ if (import.meta.hot) {
617
+ import.meta.hot.accept();
618
+ }
619
+ ```
620
+
621
+ ```tsx [app/framework/entry.ssr.tsx]
622
+ import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
623
+ import React from "react";
624
+ import type { ReactFormState } from "react-dom/client";
625
+ import { renderToReadableStream } from "react-dom/server.edge";
626
+ import { injectRSCPayload } from "rsc-html-stream/server";
627
+ import type { RscPayload } from "./entry.rsc";
628
+
629
+ export default {
630
+ fetch: async (request: Request) => {
631
+ const rscEntryModule = await import.meta.viteRsc.loadModule<typeof import("./entry.rsc")>(
632
+ "rsc",
633
+ "index"
634
+ );
635
+ return rscEntryModule.default(request);
636
+ },
637
+ };
638
+
639
+ export async function renderHTML(
640
+ rscStream: ReadableStream<Uint8Array>,
641
+ options: {
642
+ formState?: ReactFormState;
643
+ nonce?: string;
644
+ debugNoJS?: boolean;
645
+ }
646
+ ): Promise<{ stream: ReadableStream<Uint8Array>; status?: number }> {
647
+ // Duplicate one RSC stream into two.
648
+ // - one for SSR (ReactClient.createFromReadableStream below)
649
+ // - another for browser hydration payload by injecting <script>...FLIGHT_DATA...</script>.
650
+ const [rscStream1, rscStream2] = rscStream.tee();
651
+
652
+ // Deserialize RSC stream back to React VDOM
653
+ let payload: Promise<RscPayload> | undefined;
654
+ function SsrRoot() {
655
+ // Deserialization needs to be kicked off inside ReactDOMServer context
656
+ // for ReactDOMServer preinit/preloading to work
657
+ payload ??= createFromReadableStream<RscPayload>(rscStream1);
658
+ return React.use(payload).root;
659
+ }
660
+
661
+ // Render HTML (traditional SSR)
662
+ const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent("index");
663
+
664
+ let htmlStream: ReadableStream<Uint8Array>;
665
+ let status: number | undefined;
666
+
667
+ try {
668
+ htmlStream = await renderToReadableStream(<SsrRoot />, {
669
+ bootstrapScriptContent: options?.debugNoJS ? undefined : bootstrapScriptContent,
670
+ nonce: options?.nonce,
671
+ formState: options?.formState,
672
+ });
673
+ } catch {
674
+ // fallback to render an empty shell and run pure CSR on browser,
675
+ // which can replay server component error and trigger error boundary.
676
+ status = 500;
677
+ htmlStream = await renderToReadableStream(
678
+ <html>
679
+ <body>
680
+ <noscript>Internal Server Error: SSR failed</noscript>
681
+ </body>
682
+ </html>,
683
+ {
684
+ bootstrapScriptContent:
685
+ `self.__NO_HYDRATE=1;` + (options?.debugNoJS ? "" : bootstrapScriptContent),
686
+ nonce: options?.nonce,
687
+ }
688
+ );
689
+ }
690
+
691
+ let responseStream: ReadableStream<Uint8Array> = htmlStream;
692
+ if (!options?.debugNoJS) {
693
+ // Initial RSC stream is injected in HTML stream as <script>...FLIGHT_DATA...</script>
694
+ // using utility made by devongovett https://github.com/devongovett/rsc-html-stream
695
+ responseStream = responseStream.pipeThrough(
696
+ injectRSCPayload(rscStream2, {
697
+ nonce: options?.nonce,
698
+ })
699
+ );
700
+ }
701
+
702
+ return { stream: responseStream, status };
703
+ }
704
+ ```
705
+
706
+ ```tsx [app/framework/error-boundary.tsx]
707
+ "use client";
708
+
709
+ import React from "react";
710
+
711
+ // Minimal ErrorBoundary example to handle errors globally on browser
712
+ export function GlobalErrorBoundary(props: { children?: React.ReactNode }) {
713
+ return <ErrorBoundary errorComponent={DefaultGlobalErrorPage}>{props.children}</ErrorBoundary>;
714
+ }
715
+
716
+ // https://github.com/vercel/next.js/blob/33f8428f7066bf8b2ec61f025427ceb2a54c4bdf/packages/next/src/client/components/error-boundary.tsx
717
+ // https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary
718
+ class ErrorBoundary extends React.Component<{
719
+ children?: React.ReactNode;
720
+ errorComponent: React.FC<{
721
+ error: Error;
722
+ reset: () => void;
723
+ }>;
724
+ }> {
725
+ override state: { error?: Error } = {};
726
+
727
+ static getDerivedStateFromError(error: Error) {
728
+ return { error };
729
+ }
730
+
731
+ reset = () => {
732
+ this.setState({ error: null });
733
+ };
734
+
735
+ override render() {
736
+ const error = this.state.error;
737
+ if (error) {
738
+ return <this.props.errorComponent error={error} reset={this.reset} />;
739
+ }
740
+ return this.props.children;
741
+ }
742
+ }
743
+
744
+ // https://github.com/vercel/next.js/blob/677c9b372faef680d17e9ba224743f44e1107661/packages/next/src/build/webpack/loaders/next-app-loader.ts#L73
745
+ // https://github.com/vercel/next.js/blob/677c9b372faef680d17e9ba224743f44e1107661/packages/next/src/client/components/error-boundary.tsx#L145
746
+ function DefaultGlobalErrorPage(props: { error: Error; reset: () => void }) {
747
+ return (
748
+ <html>
749
+ <head>
750
+ <title>Unexpected Error</title>
751
+ </head>
752
+ <body
753
+ style={{
754
+ height: "100vh",
755
+ display: "flex",
756
+ flexDirection: "column",
757
+ placeContent: "center",
758
+ placeItems: "center",
759
+ fontSize: "16px",
760
+ fontWeight: 400,
761
+ lineHeight: "24px",
762
+ }}
763
+ >
764
+ <p>Caught an unexpected error</p>
765
+ <pre>
766
+ Error:{" "}
767
+ {import.meta.env.DEV && "message" in props.error ? props.error.message : "(Unknown)"}
768
+ </pre>
769
+ <button
770
+ onClick={() => {
771
+ React.startTransition(() => {
772
+ props.reset();
773
+ });
774
+ }}
775
+ >
776
+ Reset
777
+ </button>
778
+ </body>
779
+ </html>
780
+ );
781
+ }
782
+ ```
783
+
784
+ ```tsx [app/framework/request.tsx]
785
+ // Framework conventions (arbitrary choices for this demo):
786
+ // - Use `_.rsc` URL suffix to differentiate RSC requests from SSR requests
787
+ // - Use `x-rsc-action` header to pass server action ID
788
+ const URL_POSTFIX = "_.rsc";
789
+ const HEADER_ACTION_ID = "x-rsc-action";
790
+
791
+ // Parsed request information used to route between RSC/SSR rendering and action handling.
792
+ // Created by parseRenderRequest() from incoming HTTP requests.
793
+ type RenderRequest = {
794
+ isRsc: boolean; // true if request should return RSC payload (via _.rsc suffix)
795
+ isAction: boolean; // true if this is a server action call (POST request)
796
+ actionId?: string; // server action ID from x-rsc-action header
797
+ request: Request; // normalized Request with _.rsc suffix removed from URL
798
+ url: URL; // normalized URL with _.rsc suffix removed
799
+ };
800
+
801
+ export function createRscRenderRequest(
802
+ urlString: string,
803
+ action?: { id: string; body: BodyInit }
804
+ ): Request {
805
+ const url = new URL(urlString);
806
+ url.pathname += URL_POSTFIX;
807
+ const headers = new Headers();
808
+ if (action) {
809
+ headers.set(HEADER_ACTION_ID, action.id);
810
+ }
811
+ return new Request(url.toString(), {
812
+ method: action ? "POST" : "GET",
813
+ headers,
814
+ body: action?.body,
815
+ });
816
+ }
817
+
818
+ export function parseRenderRequest(request: Request): RenderRequest {
819
+ const url = new URL(request.url);
820
+ const isAction = request.method === "POST";
821
+ if (url.pathname.endsWith(URL_POSTFIX)) {
822
+ url.pathname = url.pathname.slice(0, -URL_POSTFIX.length);
823
+ const actionId = request.headers.get(HEADER_ACTION_ID) || undefined;
824
+ if (request.method === "POST" && !actionId) {
825
+ throw new Error("Missing action id header for RSC action request");
826
+ }
827
+ return {
828
+ isRsc: true,
829
+ isAction,
830
+ actionId,
831
+ request: new Request(url, request),
832
+ url,
833
+ };
834
+ } else {
835
+ return {
836
+ isRsc: false,
837
+ isAction,
838
+ request,
839
+ url,
840
+ };
841
+ }
842
+ }
843
+ ```
844
+ </code-tree>
845
+
846
+ This example demonstrates React Server Components (RSC) using Vite's experimental RSC plugin with Nitro. It includes server components, client components, server actions, and streaming SSR.
847
+
848
+ ## Overview
849
+
850
+ 1. **SSR Entry** handles incoming requests and renders React components to HTML
851
+ 2. **Root Component** defines the page structure as a server component
852
+ 3. **Client Components** use the `"use client"` directive for interactive parts
853
+
854
+ ## 1. SSR Entry
855
+
856
+ ```tsx [app/framework/entry.ssr.tsx]
857
+ import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
858
+ import React from "react";
859
+ import type { ReactFormState } from "react-dom/client";
860
+ import { renderToReadableStream } from "react-dom/server.edge";
861
+ import { injectRSCPayload } from "rsc-html-stream/server";
862
+ import type { RscPayload } from "./entry.rsc";
863
+
864
+ export default {
865
+ fetch: async (request: Request) => {
866
+ const rscEntryModule = await import.meta.viteRsc.loadModule<typeof import("./entry.rsc")>(
867
+ "rsc",
868
+ "index"
869
+ );
870
+ return rscEntryModule.default(request);
871
+ },
872
+ };
873
+
874
+ export async function renderHTML(
875
+ rscStream: ReadableStream<Uint8Array>,
876
+ options: {
877
+ formState?: ReactFormState;
878
+ nonce?: string;
879
+ debugNoJS?: boolean;
880
+ }
881
+ ): Promise<{ stream: ReadableStream<Uint8Array>; status?: number }> {
882
+ // Duplicate one RSC stream into two.
883
+ // - one for SSR (ReactClient.createFromReadableStream below)
884
+ // - another for browser hydration payload by injecting <script>...FLIGHT_DATA...</script>.
885
+ const [rscStream1, rscStream2] = rscStream.tee();
886
+
887
+ // Deserialize RSC stream back to React VDOM
888
+ let payload: Promise<RscPayload> | undefined;
889
+ function SsrRoot() {
890
+ // Deserialization needs to be kicked off inside ReactDOMServer context
891
+ // for ReactDOMServer preinit/preloading to work
892
+ payload ??= createFromReadableStream<RscPayload>(rscStream1);
893
+ return React.use(payload).root;
894
+ }
895
+
896
+ // Render HTML (traditional SSR)
897
+ const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent("index");
898
+
899
+ let htmlStream: ReadableStream<Uint8Array>;
900
+ let status: number | undefined;
901
+
902
+ try {
903
+ htmlStream = await renderToReadableStream(<SsrRoot />, {
904
+ bootstrapScriptContent: options?.debugNoJS ? undefined : bootstrapScriptContent,
905
+ nonce: options?.nonce,
906
+ formState: options?.formState,
907
+ });
908
+ } catch {
909
+ // fallback to render an empty shell and run pure CSR on browser,
910
+ // which can replay server component error and trigger error boundary.
911
+ status = 500;
912
+ htmlStream = await renderToReadableStream(
913
+ <html>
914
+ <body>
915
+ <noscript>Internal Server Error: SSR failed</noscript>
916
+ </body>
917
+ </html>,
918
+ {
919
+ bootstrapScriptContent:
920
+ `self.__NO_HYDRATE=1;` + (options?.debugNoJS ? "" : bootstrapScriptContent),
921
+ nonce: options?.nonce,
922
+ }
923
+ );
924
+ }
925
+
926
+ let responseStream: ReadableStream<Uint8Array> = htmlStream;
927
+ if (!options?.debugNoJS) {
928
+ // Initial RSC stream is injected in HTML stream as <script>...FLIGHT_DATA...</script>
929
+ // using utility made by devongovett https://github.com/devongovett/rsc-html-stream
930
+ responseStream = responseStream.pipeThrough(
931
+ injectRSCPayload(rscStream2, {
932
+ nonce: options?.nonce,
933
+ })
934
+ );
935
+ }
936
+
937
+ return { stream: responseStream, status };
938
+ }
939
+ ```
940
+ The SSR entry handles the rendering pipeline. It loads the RSC entry module, duplicates the RSC stream (one for SSR, one for hydration), deserializes the stream back to React VDOM, and renders it to HTML. The RSC payload is injected into the HTML for client hydration.
941
+
942
+ ## 2. Root Server Component
943
+
944
+ ```tsx [app/root.tsx]
945
+ import "./index.css"; // css import is automatically injected in exported server components
946
+ import viteLogo from "./assets/vite.svg";
947
+ import { getServerCounter, updateServerCounter } from "./action.tsx";
948
+ import reactLogo from "./assets/react.svg";
949
+ import nitroLogo from "./assets/nitro.svg";
950
+ import { ClientCounter } from "./client.tsx";
951
+
952
+ export function Root(props: { url: URL }) {
953
+ return (
954
+ <html lang="en">
955
+ <head>
956
+ {/* eslint-disable-next-line unicorn/text-encoding-identifier-case */}
957
+ <meta charSet="UTF-8" />
958
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
959
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
960
+ <title>Nitro + Vite + RSC</title>
961
+ </head>
962
+ <body>
963
+ <App {...props} />
964
+ </body>
965
+ </html>
966
+ );
967
+ }
968
+
969
+ function App(props: { url: URL }) {
970
+ return (
971
+ <div id="root">
972
+ <div>
973
+ <a href="https://vite.dev" target="_blank">
974
+ <img src={viteLogo} className="logo" alt="Vite logo" />
975
+ </a>
976
+ <a href="https://react.dev/reference/rsc/server-components" target="_blank">
977
+ <img src={reactLogo} className="logo react" alt="React logo" />
978
+ </a>
979
+
980
+ <a href="https://nitro.build" target="_blank">
981
+ <img src={nitroLogo} className="logo" alt="Nitro logo" />
982
+ </a>
983
+ </div>
984
+ <h1>Vite + RSC + Nitro</h1>
985
+ <div className="card">
986
+ <ClientCounter />
987
+ </div>
988
+ <div className="card">
989
+ <form action={updateServerCounter.bind(null, 1)}>
990
+ <button>Server Counter: {getServerCounter()}</button>
991
+ </form>
992
+ </div>
993
+ <div className="card">Request URL: {props.url?.href}</div>
994
+ <ul className="read-the-docs">
995
+ <li>
996
+ Edit <code>src/client.tsx</code> to test client HMR.
997
+ </li>
998
+ <li>
999
+ Edit <code>src/root.tsx</code> to test server HMR.
1000
+ </li>
1001
+ <li>
1002
+ Visit{" "}
1003
+ <a href="./_.rsc" target="_blank">
1004
+ <code>_.rsc</code>
1005
+ </a>{" "}
1006
+ to view RSC stream payload.
1007
+ </li>
1008
+ <li>
1009
+ Visit{" "}
1010
+ <a href="?__nojs" target="_blank">
1011
+ <code>?__nojs</code>
1012
+ </a>{" "}
1013
+ to test server action without js enabled.
1014
+ </li>
1015
+ </ul>
1016
+ </div>
1017
+ );
1018
+ }
1019
+ ```
1020
+
1021
+ Server components run only on the server. They can import CSS directly, use server-side data, and call server actions. The `ClientCounter` component is imported but runs on the client because it has the `"use client"` directive.
1022
+
1023
+ ## 3. Client Component
1024
+
1025
+ ```tsx [app/client.tsx]
1026
+ "use client";
1027
+
1028
+ import React from "react";
1029
+
1030
+ export function ClientCounter() {
1031
+ const [count, setCount] = React.useState(0);
1032
+
1033
+ return <button onClick={() => setCount((count) => count + 1)}>Client Counter: {count}</button>;
1034
+ }
1035
+ ```
1036
+
1037
+ The `"use client"` directive marks this as a client component. It hydrates on the browser and handles interactive state. Server components can import and render client components, but client components cannot import server components.
1038
+
1039
+ ## Learn More
1040
+
1041
+ - [React Server Components](https://react.dev/reference/rsc/server-components)