universal_renderer 0.3.2 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6806088bc3c54db5b3579f8d7b828c1b4e93e7d0a90c9b8bed79435c784b7e7a
4
- data.tar.gz: 5bc8d3ecb5846bdcd8b353bb1174aaf46fdef5e0ba83d7cf5a792a01117ac8b4
3
+ metadata.gz: a84ac507fd401a10c8d36c9b7600d02b4403d84bdcbd63a0c4ac1f707efe0a7f
4
+ data.tar.gz: deac3f050553555b313864a1eb06ea69ff8e8d25ed78c47a70cb0c54e562012e
5
5
  SHA512:
6
- metadata.gz: 6eff6034910021a6c6e110ef1a13e0d855e5539670fc61f1da09b08bc7af63d36c032f63c5af36f766808bee1a522b6fa2b5cb6eb0158d54d8d41d598eadf73f
7
- data.tar.gz: 66a6282ee8c5e340a128ffaf706d1493206e4d21955a1a4a8ce68ee7cabeee80b974a95d23227f98c9978509a4aeaa67c73857fa25bacafb06925fb9a03cf611
6
+ metadata.gz: cda8091a0ad83367e3a0e8bcb93d560ce4b9e778cc543b7edba4084d0e7a540eda82fcd952e40b00115fef62326d15f760de905d882c607224047565d58c9c96
7
+ data.tar.gz: 15a2798e31d87ca6eec64e0613fedf2da515db85f3b798a792b0917d1719e970862c476c51eaebf65d8550dc0885bd5619edf662819085e3a132d877a4bdf73b
data/README.md CHANGED
@@ -187,23 +187,22 @@ To set up the SSR server for your Rails application:
187
187
  4. Create an SSR entry point at `app/frontend/ssr/ssr.ts`:
188
188
 
189
189
  ```ts
190
- import { renderToString } from "react-dom/server";
190
+ import { renderToString } from "react-dom/server.node";
191
191
  import { createSsrServer } from "universal-renderer";
192
- import { createServer as createViteServer } from "vite";
193
-
194
192
  import setup from "@/ssr/setup";
195
-
196
- const vite = await createViteServer({
197
- server: { middlewareMode: true },
198
- appType: "custom",
199
- });
193
+ import {
194
+ createRenderStreamTransformer,
195
+ extractMeta,
196
+ getRequestLogger,
197
+ getStateElement,
198
+ } from "@/ssr/utils";
200
199
 
201
200
  const app = await createSsrServer({
202
- vite,
201
+ middleware: (app) => {
202
+ app.use(getRequestLogger());
203
+ },
203
204
  callbacks: {
204
- // as typeof is a little hack to get the types to resolve correctly
205
- // since Vite's ssrLoadModule doesn't include the types
206
- setup: (await vite.ssrLoadModule("@/ssr/setup")).default as typeof setup,
205
+ setup: setup,
207
206
  render: async ({ jsx, helmetContext, sheet, state }) => {
208
207
  const root = renderToString(jsx);
209
208
  const meta = extractMeta(helmetContext);
@@ -214,9 +213,16 @@ To set up the SSR server for your Rails application:
214
213
  sheet?.seal();
215
214
  queryClient?.clear();
216
215
  },
217
- onError: (error, context, errorContext) => {
218
- vite.ssrFixStacktrace(error);
219
- console.error(error);
216
+ error: (error, _, errorContext) => {
217
+ console.error(`[SSR] ${errorContext} error:`, error);
218
+ },
219
+ },
220
+ streamCallbacks: {
221
+ getReactNode: async ({ jsx }) => jsx,
222
+ getMetaTags: async ({ helmetContext }) => extractMeta(helmetContext),
223
+ createRenderStreamTransformer,
224
+ onBeforeWriteClosingHtml: async (res, { state }) => {
225
+ res.write(getStateElement(state) + "\n");
220
226
  },
221
227
  },
222
228
  });
@@ -13,7 +13,7 @@ module UniversalRenderer
13
13
  Execution._handle_node_response_streaming(
14
14
  node_res,
15
15
  response,
16
- stream_uri
16
+ stream_uri,
17
17
  )
18
18
 
19
19
  return true
@@ -28,18 +28,18 @@ module UniversalRenderer
28
28
  Execution._handle_streaming_for_node_error(
29
29
  node_res,
30
30
  response,
31
- stream_uri
31
+ stream_uri,
32
32
  )
33
33
  end
34
34
  rescue StandardError => e
35
35
  Rails.logger.error(
36
- "Error during SSR data transfer or stream writing from #{stream_uri}: #{e.class.name} - #{e.message}"
36
+ "Error during SSR data transfer or stream writing from #{stream_uri}: #{e.class.name} - #{e.message}",
37
37
  )
38
38
 
39
39
  Execution._write_generic_html_error(
40
40
  response.stream,
41
41
  "Streaming Error",
42
- "<p>A problem occurred while loading content. Please refresh.</p>"
42
+ "<p>A problem occurred while loading content. Please refresh.</p>",
43
43
  )
44
44
  ensure
45
45
  response.stream.close unless response.stream.closed?
@@ -53,7 +53,7 @@ module UniversalRenderer
53
53
 
54
54
  def _handle_streaming_for_node_error(node_res, response, stream_uri)
55
55
  Rails.logger.error(
56
- "SSR stream server at #{stream_uri} responded with #{node_res.code} #{node_res.message}."
56
+ "SSR stream server at #{stream_uri} responded with #{node_res.code} #{node_res.message}.",
57
57
  )
58
58
 
59
59
  is_potentially_viewable_error =
@@ -61,19 +61,19 @@ module UniversalRenderer
61
61
 
62
62
  if is_potentially_viewable_error
63
63
  Rails.logger.info(
64
- "Attempting to stream HTML error page from Node SSR server."
64
+ "Attempting to stream HTML error page from Node SSR server.",
65
65
  )
66
66
  Execution._stream_response_body(node_res, response.stream)
67
67
  else
68
68
  Rails.logger.warn(
69
69
  "Node SSR server error response Content-Type ('#{node_res["Content-Type"]}') is not text/html. " \
70
- "Injecting generic error message into the stream."
70
+ "Injecting generic error message into the stream.",
71
71
  )
72
72
 
73
73
  Execution._write_generic_html_error(
74
74
  response.stream,
75
75
  "Application Error",
76
- "<p>There was an issue rendering this page. Please try again later.</p>"
76
+ "<p>There was an issue rendering this page. Please try again later.</p>",
77
77
  )
78
78
  end
79
79
  end
@@ -45,7 +45,8 @@ module UniversalRenderer
45
45
  return super unless request.format.html?
46
46
 
47
47
  if use_ssr_streaming?
48
- render_ssr_stream(*args, **kwargs)
48
+ success = render_ssr_stream(*args, **kwargs)
49
+ super unless success
49
50
  else
50
51
  fetch_ssr
51
52
  super
@@ -55,36 +56,27 @@ module UniversalRenderer
55
56
  private
56
57
 
57
58
  def render_ssr_stream(*args, **kwargs)
58
- set_streaming_headers
59
-
60
59
  full_layout = render_to_string(*args, **kwargs)
61
-
62
- split_index = full_layout.index(SSR::Placeholders::META)
63
- before_meta = full_layout[0...split_index]
64
- after_meta = full_layout[split_index..]
65
-
66
- response.stream.write(before_meta)
67
-
68
60
  current_props = @universal_renderer_props.dup
69
61
 
70
62
  streaming_succeeded =
71
63
  UniversalRenderer::Client::Stream.stream(
72
64
  request.original_url,
73
65
  current_props,
74
- after_meta,
66
+ full_layout,
75
67
  response,
76
68
  )
77
69
 
78
70
  # SSR streaming failed or was not possible (e.g. server down, config missing).
79
- unless streaming_succeeded
71
+ if streaming_succeeded
72
+ response.stream.close unless response.stream.closed?
73
+ else
80
74
  Rails.logger.error(
81
75
  "SSR stream fallback: " \
82
76
  "Streaming failed, proceeding with standard rendering.",
83
77
  )
84
- response.stream.write(after_meta)
78
+ false
85
79
  end
86
-
87
- response.stream.close unless response.stream.closed?
88
80
  end
89
81
 
90
82
  def initialize_props
@@ -144,19 +136,5 @@ module UniversalRenderer
144
136
  @universal_renderer_props[prop_key] << value_to_add
145
137
  end
146
138
  end
147
-
148
- def set_streaming_headers
149
- # Tell Cloudflare / proxies not to cache or buffer.
150
- response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
151
- response.headers["Pragma"] = "no-cache"
152
- response.headers["Expires"] = "0"
153
-
154
- # Disable Nginx buffering per-response.
155
- response.headers["X-Accel-Buffering"] = "no"
156
- response.headers["Content-Type"] = "text/html"
157
-
158
- # Remove Content-Length header to prevent buffering.
159
- response.headers.delete("Content-Length")
160
- end
161
139
  end
162
140
  end
@@ -1,3 +1,3 @@
1
1
  module UniversalRenderer
2
- VERSION = "0.3.2".freeze
2
+ VERSION = "0.4.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: universal_renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thaske