@funstack/static 0.0.2 → 0.0.4

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 (50) hide show
  1. package/README.md +12 -3
  2. package/dist/bin/skill-installer.d.mts +1 -0
  3. package/dist/bin/skill-installer.mjs +12 -0
  4. package/dist/bin/skill-installer.mjs.map +1 -0
  5. package/dist/build/buildApp.mjs +4 -3
  6. package/dist/build/buildApp.mjs.map +1 -1
  7. package/dist/build/rscProcessor.mjs +9 -3
  8. package/dist/build/rscProcessor.mjs.map +1 -1
  9. package/dist/client/entry.d.mts +1 -0
  10. package/dist/client/entry.mjs +17 -9
  11. package/dist/client/entry.mjs.map +1 -1
  12. package/dist/client/globals.mjs.map +1 -1
  13. package/dist/docs/FAQ.md +5 -0
  14. package/dist/docs/GettingStarted.md +180 -0
  15. package/dist/docs/MigratingFromViteSPA.md +321 -0
  16. package/dist/docs/api/Defer.md +110 -0
  17. package/dist/docs/api/FunstackStatic.md +184 -0
  18. package/dist/docs/index.md +22 -0
  19. package/dist/docs/learn/HowItWorks.md +109 -0
  20. package/dist/docs/learn/LazyServerComponents.md +120 -0
  21. package/dist/docs/learn/OptimizingPayloads.md +107 -0
  22. package/dist/docs/learn/RSC.md +179 -0
  23. package/dist/docs/learn/SSR.md +104 -0
  24. package/dist/entries/client.d.mts +1 -1
  25. package/dist/entries/rsc-client.d.mts +2 -2
  26. package/dist/entries/rsc-client.mjs +2 -2
  27. package/dist/entries/server.d.mts +2 -2
  28. package/dist/plugin/index.d.mts +17 -1
  29. package/dist/plugin/index.d.mts.map +1 -1
  30. package/dist/plugin/index.mjs +10 -1
  31. package/dist/plugin/index.mjs.map +1 -1
  32. package/dist/rsc/defer.d.mts +18 -3
  33. package/dist/rsc/defer.d.mts.map +1 -1
  34. package/dist/rsc/defer.mjs +34 -14
  35. package/dist/rsc/defer.mjs.map +1 -1
  36. package/dist/rsc/entry.d.mts.map +1 -1
  37. package/dist/rsc/entry.mjs +85 -20
  38. package/dist/rsc/entry.mjs.map +1 -1
  39. package/dist/rsc-client/clientWrapper.d.mts +3 -3
  40. package/dist/rsc-client/clientWrapper.d.mts.map +1 -1
  41. package/dist/rsc-client/clientWrapper.mjs +2 -2
  42. package/dist/rsc-client/clientWrapper.mjs.map +1 -1
  43. package/dist/rsc-client/entry.d.mts +1 -1
  44. package/dist/rsc-client/entry.mjs +1 -1
  45. package/dist/ssr/entry.d.mts +2 -0
  46. package/dist/ssr/entry.d.mts.map +1 -1
  47. package/dist/ssr/entry.mjs +6 -2
  48. package/dist/ssr/entry.mjs.map +1 -1
  49. package/package.json +26 -11
  50. package/skills/funstack-static-knowledge/SKILL.md +44 -0
@@ -0,0 +1,321 @@
1
+ # Migrating from Vite SPA
2
+
3
+ Already have a Vite-powered React SPA? This guide walks you through migrating to FUNSTACK Static to unlock React Server Components and improved performance.
4
+
5
+ ## Overview
6
+
7
+ Migrating from a standard Vite React SPA to FUNSTACK Static involves:
8
+
9
+ 1. Installing FUNSTACK Static
10
+ 2. Adding the Vite plugin
11
+ 3. Restructuring your entry point into Root and App components
12
+ 4. Converting appropriate components to Server Components
13
+
14
+ The good news: your existing client components work as-is. You can migrate incrementally.
15
+
16
+ ## Step 1: Install Dependencies
17
+
18
+ Add FUNSTACK Static to your existing project:
19
+
20
+ ```bash
21
+ npm install @funstack/static
22
+ ```
23
+
24
+ Or with pnpm:
25
+
26
+ ```bash
27
+ pnpm add @funstack/static
28
+ ```
29
+
30
+ **Hint:** at this point, a skill installer command is available to add FUNSTACK Static knowledge to your AI agents. Run `npx funstack-static-skill-installer` or similar to add the skill. Then you can ask your AI assistant for help with the migration!
31
+
32
+ ## Step 2: Update Vite Config
33
+
34
+ Modify your `vite.config.ts` to add the FUNSTACK Static plugin:
35
+
36
+ ```typescript
37
+ import { funstackStatic } from "@funstack/static";
38
+ import react from "@vitejs/plugin-react";
39
+ import { defineConfig } from "vite";
40
+
41
+ export default defineConfig({
42
+ plugins: [
43
+ funstackStatic({
44
+ root: "./src/Root.tsx",
45
+ app: "./src/App.tsx",
46
+ }),
47
+ react(),
48
+ ],
49
+ });
50
+ ```
51
+
52
+ Note that the existing React plugin remains; FUNSTACK Static works alongside it.
53
+
54
+ ## Step 3: Create the Root Component
55
+
56
+ The Root component replaces your `index.html` file. Create `src/Root.tsx`:
57
+
58
+ ```tsx
59
+ // src/Root.tsx
60
+ import type React from "react";
61
+
62
+ export default function Root({ children }: { children: React.ReactNode }) {
63
+ return (
64
+ <html lang="en">
65
+ <head>
66
+ <meta charSet="UTF-8" />
67
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
68
+ <title>My App</title>
69
+ {/* Add your existing <head> content here */}
70
+ </head>
71
+ <body>
72
+ <div id="root">{children}</div>
73
+ </body>
74
+ </html>
75
+ );
76
+ }
77
+ ```
78
+
79
+ Move any content from your `index.html` `<head>` section into this component.
80
+
81
+ ## Step 4: Update Your App Entry Point
82
+
83
+ Your existing `main.tsx` or `index.tsx` likely looks like this:
84
+
85
+ ```tsx
86
+ // Before: src/main.tsx
87
+ import React from "react";
88
+ import ReactDOM from "react-dom/client";
89
+ import App from "./App";
90
+ import "./index.css";
91
+
92
+ ReactDOM.createRoot(document.getElementById("root")!).render(
93
+ <React.StrictMode>
94
+ <App />
95
+ </React.StrictMode>,
96
+ );
97
+ ```
98
+
99
+ With FUNSTACK Static, you no longer need this file. Instead, your `App.tsx` becomes the entry point and is automatically rendered as a Server Component:
100
+
101
+ ```tsx
102
+ // After: src/App.tsx
103
+ import "./index.css";
104
+ import { HomePage } from "./pages/HomePage";
105
+
106
+ export default function App() {
107
+ return <HomePage />;
108
+ }
109
+ ```
110
+
111
+ You can delete `main.tsx` - FUNSTACK Static handles the rendering.
112
+
113
+ ## Step 5: Mark Client Component Boundaries
114
+
115
+ In a standard Vite SPA, all components are client components. With FUNSTACK Static, components are Server Components by default.
116
+
117
+ As a starting point, it is possible to mark the App component as a client component by adding `"use client"` at the top:
118
+
119
+ ```tsx
120
+ // src/App.tsx
121
+ "use client";
122
+ // ...rest of the code
123
+ ```
124
+
125
+ This makes the entire app a client component, similar to your previous SPA.
126
+
127
+ However, to take advantage of Server Components, you should incrementally convert components to Server Components. This can be done by removing `"use client"` from components that don't need it and instead adding it only to components that require client-side interactivity.
128
+
129
+ **Note:** you only need to add `"use client"` to components that are **directly imported by Server Components**. This marks the boundary between server and client code. Components imported by other client components don't need the directive.
130
+
131
+ ```tsx
132
+ // src/components/Counter.tsx
133
+ "use client";
134
+
135
+ import { useState } from "react";
136
+ import { Button } from "./Button"; // No "use client" needed in Button.tsx
137
+
138
+ export function Counter() {
139
+ const [count, setCount] = useState(0);
140
+ return <Button onClick={() => setCount(count + 1)}>Count: {count}</Button>;
141
+ }
142
+ ```
143
+
144
+ In this example, `Counter.tsx` needs `"use client"` because it's imported by a Server Component. But `Button.tsx` doesn't need it since it's only imported by `Counter`, which is already a client component.
145
+
146
+ A component is a client component if it:
147
+
148
+ - Use client-only hooks (`useState`, `useEffect`, `useContext`, etc.)
149
+ - Attach event handlers (`onClick`, `onChange`, etc.)
150
+ - Use browser-only APIs (`window`, `document`, `localStorage`, etc.)
151
+
152
+ ## Step 6: Update Your Router (If Applicable)
153
+
154
+ If you're using React Router or another client-side router, you have two options:
155
+
156
+ ### Option A: Keep Your Existing Router
157
+
158
+ You can continue using your existing router as a client component:
159
+
160
+ ```tsx
161
+ // src/App.tsx
162
+ import { ClientRouter } from "./ClientRouter";
163
+
164
+ export default function App() {
165
+ return <ClientRouter />;
166
+ }
167
+ ```
168
+
169
+ ```tsx
170
+ // src/ClientRouter.tsx
171
+ "use client";
172
+
173
+ import { BrowserRouter, Routes, Route } from "react-router-dom";
174
+ import { Home } from "./pages/Home";
175
+ import { About } from "./pages/About";
176
+
177
+ export function ClientRouter() {
178
+ return (
179
+ <BrowserRouter>
180
+ <Routes>
181
+ <Route path="/" element={<Home />} />
182
+ <Route path="/about" element={<About />} />
183
+ </Routes>
184
+ </BrowserRouter>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ### Option B: Use a Server-Compatible Router
190
+
191
+ For better performance, consider migrating to [FUNSTACK Router](https://github.com/uhyo/funstack-router) which is a standalone router for SPAs but still integrates well with Server Components.
192
+
193
+ ```bash
194
+ npm install @funstack/router
195
+ ```
196
+
197
+ ```tsx
198
+ // src/App.tsx
199
+ import { Router } from "@funstack/router";
200
+ import { route } from "@funstack/router/server";
201
+ import { Home } from "./pages/Home";
202
+ import { About } from "./pages/About";
203
+
204
+ const routes = [
205
+ route({ path: "/", component: <Home /> }),
206
+ route({ path: "/about", component: <About /> }),
207
+ ];
208
+
209
+ export default function App() {
210
+ return <Router routes={routes} />;
211
+ }
212
+ ```
213
+
214
+ ## Step 7: Delete Unnecessary Files
215
+
216
+ After migration, you can remove:
217
+
218
+ - `src/main.tsx` (or `src/index.tsx`) - no longer needed
219
+ - `index.html` - replaced by `Root.tsx`
220
+
221
+ ## Common Migration Patterns
222
+
223
+ ### Global Styles
224
+
225
+ Import global CSS in your `App.tsx`:
226
+
227
+ ```tsx
228
+ // src/App.tsx
229
+ import "./index.css";
230
+ import "./global.css";
231
+
232
+ export default function App() {
233
+ // ...
234
+ }
235
+ ```
236
+
237
+ ### Context Providers
238
+
239
+ Wrap client-side providers in a client component:
240
+
241
+ ```tsx
242
+ // src/Providers.tsx
243
+ "use client";
244
+
245
+ import { ThemeProvider } from "./ThemeContext";
246
+ import { AuthProvider } from "./AuthContext";
247
+
248
+ export function Providers({ children }: { children: React.ReactNode }) {
249
+ return (
250
+ <ThemeProvider>
251
+ <AuthProvider>{children}</AuthProvider>
252
+ </ThemeProvider>
253
+ );
254
+ }
255
+ ```
256
+
257
+ ```tsx
258
+ // src/App.tsx
259
+ import { Providers } from "./Providers";
260
+ import { HomePage } from "./pages/HomePage";
261
+
262
+ export default function App() {
263
+ return (
264
+ <Providers>
265
+ <HomePage />
266
+ </Providers>
267
+ );
268
+ }
269
+ ```
270
+
271
+ ### Environment Variables
272
+
273
+ Client-side environment variables still work the same way with the `VITE_` prefix:
274
+
275
+ ```tsx
276
+ // In client components
277
+ const apiUrl = import.meta.env.VITE_API_URL;
278
+ ```
279
+
280
+ ## Verifying the Migration
281
+
282
+ Run the development server:
283
+
284
+ ```bash
285
+ npm run dev
286
+ ```
287
+
288
+ Check that:
289
+
290
+ - Your app loads correctly
291
+ - Interactive components work (clicks, form inputs, etc.)
292
+ - Routing works as expected
293
+ - Styles are applied correctly
294
+
295
+ Build for production:
296
+
297
+ ```bash
298
+ npm run build
299
+ ```
300
+
301
+ Your static files will be generated in `dist/public`, ready for deployment.
302
+
303
+ ## Troubleshooting
304
+
305
+ ### "Cannot use hooks in Server Component"
306
+
307
+ Add `"use client"` at the top of components that use React hooks.
308
+
309
+ ### "window is not defined"
310
+
311
+ Components using browser APIs must be client components. Add `"use client"` directive.
312
+
313
+ ### Styles not loading
314
+
315
+ Ensure CSS imports are in `App.tsx` or in client components that are actually rendered.
316
+
317
+ ## What's Next?
318
+
319
+ - Learn about [defer()](/funstack-static/api/defer) for code splitting Server Components
320
+ - Explore [Optimizing RSC Payloads](/funstack-static/learn/optimizing-payloads) for better performance
321
+ - Understand [How It Works](/funstack-static/learn/how-it-works) under the hood
@@ -0,0 +1,110 @@
1
+ # defer()
2
+
3
+ The `defer()` function enables deferred rendering for React Server Components, reducing initial data load.
4
+
5
+ You can think of this as React's `lazy` API but for Server Components.
6
+
7
+ ## Import
8
+
9
+ ```typescript
10
+ // @funstack/static/server is where utilities for server components live
11
+ import { defer } from "@funstack/static/server";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```tsx
17
+ import { defer } from "@funstack/static/server";
18
+ import { HeavyServerComponent } from "./HeavyServerComponent";
19
+
20
+ function Page() {
21
+ return (
22
+ <details>
23
+ <summary>Very long description</summary>
24
+ <Suspense fallback={<p>Loading...</p>}>
25
+ {defer(<HeavyServerComponent />)}
26
+ </Suspense>
27
+ </details>
28
+ );
29
+ }
30
+ ```
31
+
32
+ By using `defer()`, the `HeavyServerComponent` will still be rendered on the server (during build), but its data will be sent to the client as a separate RSC payload.
33
+
34
+ This means that:
35
+
36
+ - Client can start rendering the rest of the page without waiting for `HeavyServerComponent`'s data
37
+ - When the `defer(<HeavyServerComponent />)` part is rendered on the client, it will fetch the separate RSC payload and show the content.
38
+
39
+ The key point is that `HeavyServerComponent` is still a Server Component, so only the rendered HTML (and usage of Client Components inside it) is sent to the client, not the component code itself.
40
+
41
+ **Note:** `defer()` must be used inside a `Suspense` boundary since the content will be streamed in later.
42
+
43
+ ## Signature
44
+
45
+ ```typescript
46
+ export function defer(element: ReactElement, options?: DeferOptions): ReactNode;
47
+ ```
48
+
49
+ ### Parameters
50
+
51
+ - **element:** A JSX element (Server Component) to render with deferred loading.
52
+ - **options:** (optional) Configuration options for the deferred payload.
53
+
54
+ ### DeferOptions
55
+
56
+ ```typescript
57
+ interface DeferOptions {
58
+ /**
59
+ * Optional name for debugging purposes.
60
+ * In development: included in the RSC payload file name.
61
+ * In production: logged when the payload file is emitted.
62
+ */
63
+ name?: string;
64
+ }
65
+ ```
66
+
67
+ - **name:** An optional identifier to help with debugging. When provided:
68
+ - In development mode, the name is included in the RSC payload file name (e.g., `/funstack__/fun:rsc-payload/HomePage-b5698be72eea3c37`)
69
+ - In production mode, the name is logged when the payload file is emitted
70
+
71
+ ### Returns
72
+
73
+ A React Node that will stream its content separately from the main entry point.
74
+
75
+ ## When to Use defer()
76
+
77
+ Use `defer()` when you have components that:
78
+
79
+ - Renders large HTML content
80
+ - Is not immediately visible on page load (e.g., inside a collapsed section)
81
+
82
+ Typically, you will want to wrap route components with `defer()` to improve initial load performance. Otherwise, user needs to wait for contents for all pages to arrive before seeing anything.
83
+
84
+ ```tsx
85
+ import { defer } from "@funstack/static/server";
86
+ import HomePage from "./HomePage";
87
+ import AboutPage from "./AboutPage";
88
+
89
+ const routes = [
90
+ route({
91
+ path: "/",
92
+ component: defer(<HomePage />, { name: "HomePage" }),
93
+ }),
94
+ route({
95
+ path: "/about",
96
+ component: defer(<AboutPage />, { name: "AboutPage" }),
97
+ }),
98
+ // ...
99
+ ];
100
+ ```
101
+
102
+ Using the `name` option makes it easier to identify which deferred component corresponds to which payload file during development and in build logs.
103
+
104
+ ## How It Works
105
+
106
+ By default, FUNSTACK Static puts the entire app (`<App />`) into one RSC payload (`/funstack__/index.txt`). The client fetches this payload to render your SPA.
107
+
108
+ When you use `defer(<Component />)`, FUNSTACK Static creates **additional RSC payloads** for the rendering result of the element. This results in an additional emit of RSC payload files like `/funstack__/fun:rsc-payload/b5698be72eea3c37`. If you provide a `name` option, the file name will include it (e.g., `/funstack__/fun:rsc-payload/HomePage-b5698be72eea3c37`).
109
+
110
+ In the main RSC payload, the `defer` call is replaced with a client component `<DeferredComponent moduleId="fun:rsc-payload/b5698be72eea3c37" />`. This component is responsible for fetching the additional RSC payload from client and renders it when it's ready.
@@ -0,0 +1,184 @@
1
+ # funstackStatic()
2
+
3
+ The `funstackStatic()` function is the main Vite plugin that enables React Server Components for building SPAs without a runtime server.
4
+
5
+ ## Import
6
+
7
+ ```typescript
8
+ import funstackStatic from "@funstack/static";
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ // vite.config.ts
15
+ import funstackStatic from "@funstack/static";
16
+ import { defineConfig } from "vite";
17
+
18
+ export default defineConfig({
19
+ plugins: [
20
+ funstackStatic({
21
+ root: "./src/root.tsx",
22
+ app: "./src/App.tsx",
23
+ }),
24
+ ],
25
+ });
26
+ ```
27
+
28
+ ## Options
29
+
30
+ ### root (required)
31
+
32
+ **Type:** `string`
33
+
34
+ Path to the root component file. This component wraps your entire application and defines the HTML document structure (`<html>`, `<head>`, `<body>`).
35
+
36
+ ```typescript
37
+ funstackStatic({
38
+ root: "./src/root.tsx",
39
+ // ...
40
+ });
41
+ ```
42
+
43
+ The root component receives `children` as a prop:
44
+
45
+ ```tsx
46
+ // src/root.tsx
47
+ export default function Root({ children }: { children: React.ReactNode }) {
48
+ return (
49
+ <html lang="en">
50
+ <head>
51
+ <meta charSet="UTF-8" />
52
+ <title>My Site</title>
53
+ </head>
54
+ <body>{children}</body>
55
+ </html>
56
+ );
57
+ }
58
+ ```
59
+
60
+ ### app (required)
61
+
62
+ **Type:** `string`
63
+
64
+ Path to the app component file. This component defines your application's content.
65
+
66
+ ```typescript
67
+ funstackStatic({
68
+ root: "./src/root.tsx",
69
+ app: "./src/App.tsx",
70
+ });
71
+ ```
72
+
73
+ ```tsx
74
+ // src/App.tsx
75
+
76
+ export default function App() {
77
+ return (
78
+ <div>
79
+ <h1>Welcome to My Site</h1>
80
+ {/* Your fantastic application goes here */}
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+
86
+ **Note:** if your app has multiple pages, you can use a routing library here just like in a traditional SPA.
87
+
88
+ ### publicOutDir (optional)
89
+
90
+ **Type:** `string`
91
+ **Default:** `"dist/public"`
92
+
93
+ Output directory for the generated static files.
94
+
95
+ ```typescript
96
+ funstackStatic({
97
+ root: "./src/root.tsx",
98
+ app: "./src/App.tsx",
99
+ publicOutDir: "build/static",
100
+ });
101
+ ```
102
+
103
+ ### ssr (optional)
104
+
105
+ **Type:** `boolean`
106
+ **Default:** `false`
107
+
108
+ Enable server-side rendering of the App component.
109
+
110
+ When `false` (default), only the Root shell is rendered to HTML at build time. The App component's RSC payload is fetched separately and rendered client-side using `createRoot`. This results in faster initial HTML delivery but requires JavaScript to display the App content.
111
+
112
+ When `true`, both the Root and App components are fully rendered to HTML. The client hydrates the existing HTML using `hydrateRoot`, which can improve perceived performance and SEO since the full content is visible before JavaScript loads.
113
+
114
+ ```typescript
115
+ funstackStatic({
116
+ root: "./src/root.tsx",
117
+ app: "./src/App.tsx",
118
+ ssr: true, // Enable full SSR
119
+ });
120
+ ```
121
+
122
+ **Note:** In both modes, React Server Components are used - the `ssr` option only controls whether the App's HTML is pre-rendered or rendered client-side.
123
+
124
+ ### clientInit (optional)
125
+
126
+ **Type:** `string`
127
+
128
+ Path to a module that runs on the client side **before React hydration**. Use this for client-side instrumentation like Sentry, analytics, or feature flags.
129
+
130
+ The module is imported for its side effects only - no exports are needed.
131
+
132
+ ```typescript
133
+ funstackStatic({
134
+ root: "./src/root.tsx",
135
+ app: "./src/App.tsx",
136
+ clientInit: "./src/client-init.ts",
137
+ });
138
+ ```
139
+
140
+ Example client init file:
141
+
142
+ ```typescript
143
+ // src/client-init.ts
144
+ import * as Sentry from "@sentry/browser";
145
+
146
+ Sentry.init({
147
+ dsn: "https://your-sentry-dsn",
148
+ environment: import.meta.env.MODE,
149
+ });
150
+ ```
151
+
152
+ **Note:** Errors in the client init module will propagate normally and prevent the app from rendering.
153
+
154
+ ## Full Example
155
+
156
+ ```typescript
157
+ // vite.config.ts
158
+ import { funstackStatic } from "@funstack/static";
159
+ import { defineConfig } from "vite";
160
+
161
+ export default defineConfig({
162
+ plugins: [
163
+ funstackStatic({
164
+ root: "./src/root.tsx",
165
+ app: "./src/App.tsx",
166
+ publicOutDir: "dist/public",
167
+ }),
168
+ ],
169
+ });
170
+ ```
171
+
172
+ ## Vite Commands
173
+
174
+ You can use the same Vite commands you would use in a normal Vite project:
175
+
176
+ - `vite dev` - Starts the development server
177
+ - `vite build` - Builds the static files
178
+ - `vite preview` - Previews the built static files locally
179
+
180
+ ## See Also
181
+
182
+ - [Getting Started](/funstack-static/getting-started) - Quick start guide
183
+ - [defer()](/funstack-static/api/defer) - Deferred rendering for streaming
184
+ - [React Server Components](/funstack-static/learn/rsc) - Understanding RSC
@@ -0,0 +1,22 @@
1
+ # @funstack/static Documentation
2
+
3
+ A Vite plugin for building static sites with React Server Components.
4
+
5
+ ## Available Documentation
6
+
7
+ - [FAQ](./FAQ.md) - This is a bug in React itself. Please wait for [the fix](https://github.com/facebook/react/pull/34760) to be released.
8
+ - [Getting Started](./GettingStarted.md) - Welcome to **FUNSTACK Static**! Build high-performance Single Page Applications powered by React Server Components - no server required at runtime.
9
+ - [Migrating from Vite SPA](./MigratingFromViteSPA.md) - Already have a Vite-powered React SPA? This guide walks you through migrating to FUNSTACK Static to unlock React Server Components and improved performance.
10
+
11
+ ### API
12
+
13
+ - [defer()](./api/Defer.md) - The `defer()` function enables deferred rendering for React Server Components, reducing initial data load.
14
+ - [funstackStatic()](./api/FunstackStatic.md) - The `funstackStatic()` function is the main Vite plugin that enables React Server Components for building SPAs without a runtime server.
15
+
16
+ ### Learn
17
+
18
+ - [How It Works](./learn/HowItWorks.md) - FUNSTACK Static is a React framework that leverages React Server Components (RSC) to build a fully static Single Page Application. The result is a set of files that can be deployed to **any static file hosting service** - no server required at runtime.
19
+ - [Using lazy() in Server Components](./learn/LazyServerComponents.md) - React's `lazy()` API is typically associated with client-side code splitting. However, it can also be used in server environments to reduce the initial response time of the development server by deferring the work needed to compute your application.
20
+ - [Optimizing RSC Payloads](./learn/OptimizingPayloads.md) - FUNSTACK Static uses React Server Components (RSC) to pre-render your application at build time. By default, all content is bundled into a single RSC payload. This page explains how to split that payload into smaller chunks for better loading performance.
21
+ - [React Server Components](./learn/RSC.md) - [React Server Components (RSC)](https://react.dev/reference/rsc/server-components) are a new paradigm for building React applications where components can run on the server (or at build time) rather than in the browser.
22
+ - [Server-Side Rendering](./learn/SSR.md) - In FUNSTACK Static, **Server-Side Rendering (SSR)** means a build-time process that pre-renders your React components (including client components) to HTML. This can make the initial paint faster.