@rsc-kit/mcp 0.15.0 → 0.16.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.
- package/dist/answers.js +2 -0
- package/dist/answers.js.map +1 -1
- package/dist/bundleGuides.d.ts +7 -2
- package/dist/bundleGuides.js +14 -6
- package/dist/bundleGuides.js.map +1 -1
- package/dist/recipes.js +57 -11
- package/dist/recipes.js.map +1 -1
- package/dist/report.d.ts +2 -0
- package/dist/report.js.map +1 -1
- package/guides/coming-from-next.md +151 -0
- package/guides/getting-started.md +132 -0
- package/guides/index.json +25 -0
- package/guides/installation.md +338 -0
- package/guides/introduction.md +119 -0
- package/guides/no-javascript.md +48 -11
- package/guides/quick-start.md +99 -0
- package/package.json +1 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Introduction
|
|
2
|
+
|
|
3
|
+
> React Server Components as a Vite plugin, deployed wherever you like.
|
|
4
|
+
|
|
5
|
+
`rsc-kit` is a Vite plugin that gives you React Server Components. You write
|
|
6
|
+
pages, layouts and server actions the way you would in the Next.js App Router;
|
|
7
|
+
it renders them, streams the HTML, and turns links into navigations that replace
|
|
8
|
+
only the part of the page that changed.
|
|
9
|
+
|
|
10
|
+
It brings no build system of its own — it is a Vite plugin — and it does not
|
|
11
|
+
write a server for you either. [Nitro](https://nitro.build) builds one around
|
|
12
|
+
your route tree, so where an app runs is a preset: Bun, Node, a Cloudflare
|
|
13
|
+
Worker, Vercel, Netlify, Deno.
|
|
14
|
+
|
|
15
|
+
## What an app looks like
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
src/app/
|
|
19
|
+
layout.tsx the document — <html>, <head>, <body>
|
|
20
|
+
loading.tsx Suspense fallback for everything below
|
|
21
|
+
page.tsx GET /
|
|
22
|
+
posts/
|
|
23
|
+
[slug]/
|
|
24
|
+
page.tsx GET /posts/:slug
|
|
25
|
+
@modal/
|
|
26
|
+
default.tsx a parallel slot, empty until something fills it
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Nothing registers those files. The plugin reads the directory at build time and
|
|
30
|
+
generates the entry that knows about them.
|
|
31
|
+
|
|
32
|
+
```tsx title="src/app/posts/[slug]/page.tsx"
|
|
33
|
+
import { findPost } from '../../../data'
|
|
34
|
+
|
|
35
|
+
export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
|
|
36
|
+
const { slug } = await params
|
|
37
|
+
const post = await findPost(slug)
|
|
38
|
+
|
|
39
|
+
if (!post) return <h1>No such post</h1>
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<article>
|
|
43
|
+
<h1>{post.title}</h1>
|
|
44
|
+
<p>{post.body}</p>
|
|
45
|
+
</article>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A server component is an ordinary async function. It imports its data module
|
|
51
|
+
directly, and neither the module nor its secrets reach the browser.
|
|
52
|
+
|
|
53
|
+
## What you get
|
|
54
|
+
|
|
55
|
+
<CardGrid>
|
|
56
|
+
<Card title="Streaming, not waterfalls" icon="ph:waves">
|
|
57
|
+
The shell paints before the data resolves. Suspense boundaries fill in as
|
|
58
|
+
they finish, in whatever order they finish.
|
|
59
|
+
</Card>
|
|
60
|
+
<Card title="Navigations that keep the page" icon="ph:arrows-left-right">
|
|
61
|
+
A navigation sends the layout chain it already has, and the server answers
|
|
62
|
+
with only the part that changed. Scroll, focus and half-typed forms survive.
|
|
63
|
+
</Card>
|
|
64
|
+
<Card title="Parallel routes and interception" icon="ph:frame-corners">
|
|
65
|
+
`@slot` directories render alongside the page. `(.)folder` opens a route as
|
|
66
|
+
a modal over the page you were on, and as a real page on refresh.
|
|
67
|
+
</Card>
|
|
68
|
+
<Card title="Server actions" icon="ph:lightning">
|
|
69
|
+
`"use server"` makes an async function callable from a client component.
|
|
70
|
+
The body never ships; the call becomes one POST.
|
|
71
|
+
</Card>
|
|
72
|
+
<Card title="Queries, without an endpoint" icon="ph:magnifying-glass">
|
|
73
|
+
`query()` marks a read. It travels as a GET, so it can be cached and
|
|
74
|
+
prefetched — and reads that happen together leave as one request.
|
|
75
|
+
</Card>
|
|
76
|
+
<Card title="Frozen where it can be" icon="ph:snowflake">
|
|
77
|
+
Pages that ask for nothing dynamic are rendered at build time. Pages that do
|
|
78
|
+
get their shell frozen and their data streamed.
|
|
79
|
+
</Card>
|
|
80
|
+
<Card title="An export target" icon="ph:folder-open">
|
|
81
|
+
The same app can build to a directory of files and be served by anything —
|
|
82
|
+
including a CDN with no origin at all.
|
|
83
|
+
</Card>
|
|
84
|
+
</CardGrid>
|
|
85
|
+
|
|
86
|
+
## Where it runs
|
|
87
|
+
|
|
88
|
+
You do not write a server. [Nitro](https://nitro.build) builds one from your
|
|
89
|
+
route tree, and where it runs is one line in your Vite config:
|
|
90
|
+
|
|
91
|
+
```ts title="vite.config.ts"
|
|
92
|
+
nitro({ preset: 'bun' })
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Swap the preset for `node`, `cloudflare_module`, `vercel`, `netlify` or `deno`
|
|
96
|
+
and the same app deploys there instead. The build produces a `.output`
|
|
97
|
+
directory; nothing else changes.
|
|
98
|
+
|
|
99
|
+
## What it is not
|
|
100
|
+
|
|
101
|
+
<Aside type="note" title="No data layer, no CSS pipeline, no dev server of its own">
|
|
102
|
+
The build runs your project's Vite config, so Tailwind, PostCSS and the rest
|
|
103
|
+
are configured the way they are in any Vite app. Data access is an import.
|
|
104
|
+
There is no `getServerSideProps` equivalent, and no request context to learn.
|
|
105
|
+
</Aside>
|
|
106
|
+
|
|
107
|
+
## Where to go next
|
|
108
|
+
|
|
109
|
+
<CardGrid>
|
|
110
|
+
<Card title="Getting started" icon="ph:play">
|
|
111
|
+
[Build and deploy your first app →](/getting-started)
|
|
112
|
+
</Card>
|
|
113
|
+
<Card title="Routing" icon="ph:tree-structure">
|
|
114
|
+
[Pages, layouts, slots and navigation →](/guides/routing)
|
|
115
|
+
</Card>
|
|
116
|
+
<Card title="How it works" icon="ph:gear">
|
|
117
|
+
[What happens between a request and a page →](/reference/how-it-works)
|
|
118
|
+
</Card>
|
|
119
|
+
</CardGrid>
|
package/guides/no-javascript.md
CHANGED
|
@@ -3,24 +3,61 @@
|
|
|
3
3
|
> Rendering a route to HTML and stopping there.
|
|
4
4
|
|
|
5
5
|
Some pages have nothing to hydrate. A marketing page, a changelog, an article.
|
|
6
|
-
For those, shipping React is paying about 70 kB gzipped for nothing
|
|
6
|
+
For those, shipping React is paying about 70 kB gzipped for nothing — so the
|
|
7
|
+
build does not.
|
|
8
|
+
|
|
9
|
+
## It is automatic
|
|
10
|
+
|
|
11
|
+
A route that freezes whole, renders **no client component** of yours, and has
|
|
12
|
+
**no server action** in its tree is stored without the bootstrap script. No
|
|
13
|
+
React, no Flight client, no router. The build says so:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
○ /about no js
|
|
17
|
+
no client components, so ships no javascript
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Nothing to declare. The check is made on the rendered tree, not the source,
|
|
21
|
+
so a client component reached through a shared layout counts — which is why
|
|
22
|
+
most pages in an app with a `<Link>` in its header keep the runtime, and a
|
|
23
|
+
route group with its own plain layout can drop it.
|
|
24
|
+
|
|
25
|
+
The line is drawn at what the runtime would *do*. A client component needs
|
|
26
|
+
hydrating. A `<form action={serverFn}>` written in a server component needs
|
|
27
|
+
React to submit it. A `<Suspense>` hole that was not filled at build time
|
|
28
|
+
needs the client to fill it, which is why only a route stored whole
|
|
29
|
+
qualifies. Everything else — anchors, styles, a third-party `<script>` — works
|
|
30
|
+
the same with or without.
|
|
31
|
+
|
|
32
|
+
Navigation is unchanged in both directions. A page with no client component
|
|
33
|
+
has no `<Link>`, so its anchors were already full loads. A `<Link>` elsewhere
|
|
34
|
+
that points *at* it still fetches its flight payload and swaps the segment,
|
|
35
|
+
because that payload is still written from the render with the runtime.
|
|
36
|
+
|
|
37
|
+
## Declaring it
|
|
38
|
+
|
|
39
|
+
To force it on, for a page that renders a client component you are content
|
|
40
|
+
to leave inert:
|
|
7
41
|
|
|
8
42
|
```tsx title="src/app/about/page.tsx"
|
|
9
43
|
export const clientJs = false
|
|
10
|
-
|
|
11
|
-
export default function AboutPage() {
|
|
12
|
-
return <h1>About</h1>
|
|
13
|
-
}
|
|
14
44
|
```
|
|
15
45
|
|
|
16
|
-
|
|
17
|
-
|
|
46
|
+
A page stored this way still registers the [service worker](/guides/offline)
|
|
47
|
+
when the app has one: the runtime's one-line registration is inlined in its
|
|
48
|
+
place, so a visitor who lands here first gets the worker the second visit is
|
|
49
|
+
for. What such a page cannot show is the update prompt, which is a client
|
|
50
|
+
component. To keep the runtime on a page the build would otherwise strip, say
|
|
51
|
+
so:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
export const clientJs = true
|
|
55
|
+
```
|
|
18
56
|
|
|
19
|
-
## What stops working
|
|
57
|
+
## What stops working when you declare it
|
|
20
58
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
combination rather than shipping it:
|
|
59
|
+
With `clientJs = false`, anything interactive stops working, which is why the
|
|
60
|
+
build refuses the combination rather than shipping it:
|
|
24
61
|
|
|
25
62
|
```
|
|
26
63
|
app/about/page.tsx declares clientJs = false but renders client components:
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Quick start
|
|
2
|
+
|
|
3
|
+
> A running app in one command, or added to a project you already have.
|
|
4
|
+
|
|
5
|
+
## A new app
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun create rsc-kit@latest my-app
|
|
9
|
+
cd my-app
|
|
10
|
+
bun run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
That is it. You get a page, a layout, a client component and a Vite config,
|
|
14
|
+
wired together and running. There is no server file — Nitro builds one from the
|
|
15
|
+
preset in that config when you build.
|
|
16
|
+
|
|
17
|
+
When you are ready to ship:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
bun run build
|
|
21
|
+
bun run start
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The build prints what it did:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
○ /
|
|
28
|
+
|
|
29
|
+
○ (Static) prerendered as static content
|
|
30
|
+
|
|
31
|
+
1 static
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Pages marked `○` are **static**: rendered once at build time rather than for
|
|
35
|
+
each visitor.
|
|
36
|
+
|
|
37
|
+
## An app you already have
|
|
38
|
+
|
|
39
|
+
Already have a project? Add rsc-kit to it:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
bunx rsc-kit@latest init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It reads your `package.json`, works out which server you use and where your
|
|
46
|
+
source lives, and writes only what is missing:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
server hono
|
|
50
|
+
source src
|
|
51
|
+
react will be added
|
|
52
|
+
|
|
53
|
+
+ src/app/layout.tsx
|
|
54
|
+
+ src/app/page.tsx
|
|
55
|
+
+ vite.config.ts
|
|
56
|
+
~ package.json — added @rsc-kit/core, react, react-dom, vite, nitro, …
|
|
57
|
+
~ scripts — dev, build, start, compile, typecheck
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
No server file. Nitro builds one around the route tree, so the app owns a route
|
|
61
|
+
tree and a vite config and nothing in between.
|
|
62
|
+
|
|
63
|
+
**It never overwrites anything.** If you already have a `vite.config.ts`, it
|
|
64
|
+
prints the edit to make instead of replacing work you have done. Running it twice is safe — the second run just tells you what is already
|
|
65
|
+
in place.
|
|
66
|
+
|
|
67
|
+
Then:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
bun install
|
|
71
|
+
bun run dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Add a page
|
|
75
|
+
|
|
76
|
+
Routes are directories under `src/app`. Create a folder, put a `page.tsx` in
|
|
77
|
+
it, and it exists:
|
|
78
|
+
|
|
79
|
+
```tsx title="src/app/about/page.tsx"
|
|
80
|
+
export default function AboutPage() {
|
|
81
|
+
return <h1>About</h1>
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
bun run build # the route tree is read at build time
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Doing it by hand
|
|
90
|
+
|
|
91
|
+
If you would rather wire it up yourself — or the CLI cannot reach your
|
|
92
|
+
setup — [Installation](/installation) walks through the same result one file at
|
|
93
|
+
a time.
|
|
94
|
+
|
|
95
|
+
## Where next
|
|
96
|
+
|
|
97
|
+
- [Routing](/guides/routing) — layouts, dynamic segments, parallel slots
|
|
98
|
+
- [Server actions](/guides/server-actions) — mutations without an API route
|
|
99
|
+
- [Where it runs](/hosts/where-it-runs) — presets, and compiling to a binary
|
package/package.json
CHANGED