You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`fastify-renderer` renders client side JavaScript applications on the server to improve the user experience.
6
+
`fastify-renderer` renders client side JavaScript applications on the server to improve user experience. `fastify-renderer` is a standard Fastify plugin that mounts into an existing fastify application, so it's easy to use for only some routes.
7
7
8
-
- It renders client side apps server side with minimal setup
9
-
- Supports optional async work ahead of time using handy server side bits like a database connection or session stored in redis
10
-
- Serves server side props to client side pages as the navigations happen client side
11
-
- Control things outside the inner application like the `<head/>` tag when server rendering
8
+
`fastify-renderer` works similarly to `next.js` and other SSR frameworks, where the first pageload a user makes is server side rendered, and then a client side app is booted. Subsequent navigations are handled client side, where the client makes a `fetch` call to retrieve the next set of `props` for the next page as JSON data, instead of re-rendering the whole page server side.
12
9
10
+
Features:
11
+
12
+
- React SSR for fastify using `vite`
13
+
- Allows async work ahead of time to produce props for the page, which means you can use a database connection, redis, or whatever else you have server side in Fastify
14
+
- Support for rich React component layouts wrapping each page
15
+
- Support for fastify plugin encapsulation contexts, so can be used to support different "areas" of an app within the same fastify server
16
+
- Support for managing the full document shape using EJS templates
13
17
14
18
## Installation
15
19
@@ -22,7 +26,6 @@ yarn install fastify-renderer
22
26
23
27
## Registering the plugin
24
28
25
-
26
29
```js
27
30
importfastifyfrom'fastify'
28
31
importrendererfrom'fastify-renderer'
@@ -31,7 +34,40 @@ const server = fastify()
31
34
server.register(renderer)
32
35
```
33
36
37
+
After registering the plugin, you need to set a render config for a Fastify encapsulation context.
38
+
39
+
```js
40
+
// at the root, you can set the render config for the whole server
41
+
server.setRenderConfig({
42
+
layout:'../client/Layout.jsx',
43
+
})
44
+
45
+
// or within a context, you can set the render config for just routes defined in that context
Once the plugin is registered, any route in your Fastify application can render components. To make a route render a component, pass a component path as the `render` option to the route options:
Unlike a normal Fastify route handler, render route functions don't use `reply.send` to return HTML content. Instead, your route handler function should return a `props` object. This `props` object will be passed to the rendered component when being rendered server side, and will be fetched from this route and passed to the component when being rendered client side.
68
+
34
69
### Configuration options
70
+
35
71
You can optionally provide configuration options to the plugin:
36
72
37
73
-`renderer` - Object that provides the rendering options
@@ -40,30 +76,65 @@ You can optionally provide configuration options to the plugin:
40
76
-`vite` - Vite [InlineConfig](https://vitejs.dev/guide/api-javascript.html#inlineconfig) options
41
77
-`base` - The base path we want our renderer to use
42
78
-`layout` - The path to a layout component inside of which other routes will be rendered
43
-
-`document` - HTML template inside of which everything is rendered
79
+
-`document` - HTML template inside of which everything is rendered. The `template` option accepts a function which should return a `ReadableStream` to produce the output HTML.
44
80
-`devMode` - Boolean, when true a vite devServer is created
45
81
-`outDir` - The directory where the files generated by the Vite build will be created
46
82
-`assetsHost` - The host url from which files will be accessible to the browser
47
-
-`hooks` - Array of FastifyRendererHook
48
-
-`name` - Optional string value
83
+
-`hooks` - Array of FastifyRendererHook
84
+
-`name` - Optional string value
49
85
-`heads` - Function that will return html tags to be appended to the document head tag
50
86
-`tails` - Function that will return html tags to be appended to the document body tag
51
87
-`transform` - Function that will be run to transform the root react element
52
88
-`postRenderHeads` - Function (called after render) that will return html tags to be appended to the document head tag. Useful when injecting styles that rely on rendering first.
53
89
90
+
The plugin will render the component server side and return it, where as the route handler will return the props to the frontend when needed.
The raw HTML wrapper for each SSR page can be controlled with the `document` option passed at the root level plugin config or with `.setRenderConfig`. The `document` option accepts a function which is given render data, and should return a `ReadableStream` object for piping to the browser. We use a streaming interface in order to stream the result efficiently to the browser before the whole render is complete.
95
+
96
+
The function is passed a `data` object which should be used for interpolating values into your output stream. Here's the shape of the `data` object:
97
+
98
+
```typescript
99
+
/** Data passed to the template function by the renderer */
100
+
interfaceTemplateData<Props> {
101
+
/** The content for including in the `<head/>` tag of the rendered document */
102
+
head:NodeJS.ReadableStream
103
+
/** The content for including after the app just before the `</body>` tag of the rendered document */
104
+
tail:NodeJS.ReadableStream
105
+
/** The main content for the app */
106
+
content:string|NodeJS.ReadableStream
107
+
/** The props object generated by the route handler for this render */
108
+
props:Props
109
+
}
62
110
```
63
-
The plugin will render the component server side and return it, where as the route handler will return the props to the frontend when needed.
64
111
112
+
Usually, the `stream-template` package is used for this for super easy interpolation of streams.
- mounts a `vite` server as a fastify plugin that knows how to transform code to be run server side.
68
139
- provides renderers that use vite for react and other popular frameworks (Currently only React is supported)
69
140
- provides a convention for async ahead of time work to pass data into renderers
@@ -76,7 +147,7 @@ The goal of fastify-renderer is to bring a great developer/user experience and i
76
147
- next.js has a great developer experience but blocks the main thread when rendering react.
77
148
- next.js uses express and webpack underneath, both of which have much better performing alternatives
78
149
- next.js must be both the bundler and the server, it's hard to mount it into an existing system like fastify and play nice with all the other plugins you might want to use when doing :gasp: server side rendered :gasp: applications
79
-
- vite is awesome but also wants to be the server and keep the frontend entirely seperate from the backend
150
+
- vite is awesome but also wants to be the server and keep the frontend entirely separate from the backend
80
151
- server side rendering is hard and reinventing that wheel is no fun
81
152
- hot reloading in development is hard and reinventing that wheel is no fun
82
153
- bundling for production is hard and reinventing that wheel is no fun
@@ -86,8 +157,8 @@ The goal of fastify-renderer is to bring a great developer/user experience and i
86
157
87
158
-[Navigating between routes from different Fastify contexts](./docs/fastify-contexts)
88
159
89
-
90
160
## Roadmap
161
+
91
162
- Add support for rendering outside the main thread by using Piscina.js
92
163
- Add support for Vue and other frontend frameworks
0 commit comments