humid 0.6.0 → 1.0.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 +4 -4
- data/README.md +65 -67
- data/lib/humid/version.rb +1 -1
- data/lib/humid.rb +2 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f8a07ab8d934750bbdb01dc4596426d02edd7733d7bf87093b8ca36d5abbbb33
|
|
4
|
+
data.tar.gz: d3c9f28d92d637d8d4eb20e78676a0eacf09d7c922c0583448f3aacc1befe4fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 311cdf7125016802906bc28b7545c80c22e01709ebe679ead307f68783bab051a9e30bc634b777ce41802ad9d6564288305c593aee5da05a40e853b8a7ce31f2
|
|
7
|
+
data.tar.gz: 43777369d6c7b2525957d11117be0b1df56e960dbea0ca7be822ebb1b0d7c1e9af5f406fea47619d7f50829e203f610fb1074b1435b6ccce310453f1db04bf05
|
data/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./images/svg/humid-icon.svg" alt="Humid" width="128" />
|
|
3
|
+
<h1>Humid</h1>
|
|
4
|
+
<p>A few helpers for Javascript server-side rendering on Rails with <a
|
|
5
|
+
href="https://github.com/rubyjs/mini_racer">mini_racer</a></p>
|
|
6
|
+
</div>
|
|
2
7
|
|
|
3
8
|

|
|
4
9
|
|
|
@@ -12,16 +17,20 @@ returns an HTML string.
|
|
|
12
17
|
|
|
13
18
|
## Design
|
|
14
19
|
|
|
15
|
-
Humid is designed
|
|
16
|
-
rendering. Your application fetches everything needed, passes it as props, and
|
|
17
|
-
Humid returns the rendered HTML in a single synchronous call. It does not
|
|
18
|
-
support streaming or async data fetching during render.
|
|
20
|
+
Humid is designed with 2 goals in mind:
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
1. Its for the common case where all data is gathered before rendering. Your
|
|
23
|
+
application fetches everything needed, passes it as props, and Humid returns
|
|
24
|
+
the rendered HTML in a single synchronous call. It does not support streaming
|
|
25
|
+
or async data fetching during render.
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
2. Its a stepping stone for when you want to scale on the edge using
|
|
28
|
+
[Cloudflare V8 isolates](https://developers.cloudflare.com/workers/reference/how-workers-works/)
|
|
29
|
+
.`mini_racer` is a bare V8 environment, if your JS bundle works with
|
|
30
|
+
`mini_racer`, it'll work on Cloudflare V8 isolates.
|
|
31
|
+
|
|
32
|
+
> [!NOTE]
|
|
33
|
+
> See the [sample](./sample/) for a complete working example.
|
|
25
34
|
|
|
26
35
|
## Installation
|
|
27
36
|
|
|
@@ -43,25 +52,25 @@ Add an initializer to configure the default options for `Humid.render`. These
|
|
|
43
52
|
are overridable on `Humid.render`.
|
|
44
53
|
|
|
45
54
|
```ruby
|
|
46
|
-
#
|
|
55
|
+
# config/initializers/humid.rb
|
|
47
56
|
|
|
48
57
|
Humid.configure do |config|
|
|
49
58
|
# Path to your build file located in `app/assets/builds/`. You should use a
|
|
50
59
|
# separate build apart from your `application.js`.
|
|
51
60
|
#
|
|
52
61
|
# Required
|
|
53
|
-
config.application_path = Rails.root.join(
|
|
62
|
+
config.application_path = Rails.root.join("app/assets/builds/server_rendering.js")
|
|
54
63
|
|
|
55
64
|
# Path to your source map file
|
|
56
65
|
#
|
|
57
66
|
# Optional
|
|
58
|
-
config.source_map_path = Rails.root.join(
|
|
67
|
+
config.source_map_path = Rails.root.join("app/assets/builds/server_rendering.js.map")
|
|
59
68
|
|
|
60
69
|
# Raise errors if JS rendering failed. If false, the error will be
|
|
61
|
-
# logged
|
|
70
|
+
# logged and Humid.render will return an empty string.
|
|
62
71
|
#
|
|
63
72
|
# Defaults to true.
|
|
64
|
-
config.raise_render_errors = Rails.env.
|
|
73
|
+
config.raise_render_errors = Rails.env.local?
|
|
65
74
|
|
|
66
75
|
# The logger instance.
|
|
67
76
|
# `console.log` and friends (`warn`, `error`) are delegated to
|
|
@@ -72,10 +81,21 @@ Humid.configure do |config|
|
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
if Rails.env.local?
|
|
75
|
-
# Use single_threaded mode for
|
|
84
|
+
# Use single_threaded mode for dev and test environments.
|
|
85
|
+
# This will also work for mini_test parallel tests
|
|
76
86
|
MiniRacer::Platform.set_flags! :single_threaded
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
MINI_RACER_SSR = { context: MiniRacer::Context.new(timeout: 1000, ensure_gc_after_idle: 2000) }
|
|
88
|
+
|
|
89
|
+
# Reload the context when the SSR bundle changes
|
|
90
|
+
ssr_checker = ActiveSupport::FileUpdateChecker.new([Humid.config.application_path.to_s]) do
|
|
91
|
+
MINI_RACER_SSR[:context].dispose
|
|
92
|
+
MINI_RACER_SSR[:context] = MiniRacer::Context.new(timeout: 1000, ensure_gc_after_idle: 2000)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Rails.application.reloaders << ssr_checker
|
|
96
|
+
Rails.application.reloader.to_run do
|
|
97
|
+
ssr_checker.execute_if_updated
|
|
98
|
+
end
|
|
79
99
|
end
|
|
80
100
|
```
|
|
81
101
|
|
|
@@ -117,22 +137,20 @@ require("source-map-support").install({
|
|
|
117
137
|
### Your webserver
|
|
118
138
|
|
|
119
139
|
On production, keep in mind that `mini_racer` is **thread safe, but not fork
|
|
120
|
-
safe**. When using with web servers that employ forking, create
|
|
121
|
-
|
|
122
|
-
should be no context created on the master process.**
|
|
140
|
+
safe**. When using with web servers that employ forking, create the context
|
|
141
|
+
on worker boot. **There should be no context created on the master process.**
|
|
123
142
|
|
|
124
143
|
For example with puma:
|
|
125
144
|
|
|
126
145
|
```ruby
|
|
127
146
|
# config/puma.rb
|
|
128
147
|
on_worker_boot do
|
|
129
|
-
ctx = MiniRacer::Context.new(timeout:
|
|
130
|
-
|
|
131
|
-
MINI_RACER_CONTEXT = Humid.prepare(ctx)
|
|
148
|
+
ctx = MiniRacer::Context.new(timeout: 1000, ensure_gc_after_idle: 2000)
|
|
149
|
+
MINI_RACER_SSR = { context: Humid.prepare(ctx) }
|
|
132
150
|
end
|
|
133
151
|
|
|
134
152
|
on_worker_shutdown do
|
|
135
|
-
|
|
153
|
+
MINI_RACER_SSR[:context].dispose
|
|
136
154
|
end
|
|
137
155
|
```
|
|
138
156
|
|
|
@@ -142,22 +160,23 @@ end
|
|
|
142
160
|
You can also override config options per-context:
|
|
143
161
|
|
|
144
162
|
```ruby
|
|
145
|
-
|
|
163
|
+
ctx = Humid.prepare(
|
|
146
164
|
MiniRacer::Context.new(timeout: 1000),
|
|
147
165
|
application_path: Rails.root.join("other_bundle.js"),
|
|
148
166
|
logger: nil
|
|
149
167
|
)
|
|
168
|
+
MINI_RACER_SSR = { context: ctx }
|
|
150
169
|
```
|
|
151
170
|
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
> [!NOTE]
|
|
172
|
+
> If you pass a context that was already prepared, `prepare` will noop and return the context back to you.
|
|
154
173
|
|
|
155
174
|
### Call `Humid.render`
|
|
156
175
|
|
|
157
176
|
And finally call `render` from ERB.
|
|
158
177
|
|
|
159
178
|
```ruby
|
|
160
|
-
<%= Humid.render(
|
|
179
|
+
<%= Humid.render(MINI_RACER_SSR[:context], json).html_safe %>
|
|
161
180
|
```
|
|
162
181
|
|
|
163
182
|
Instrumentation is included:
|
|
@@ -209,17 +228,19 @@ The default formatter returns `message` unchanged.
|
|
|
209
228
|
|
|
210
229
|
## Server-side libraries that detect node.js envs.
|
|
211
230
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
231
|
+
Some libraries check for Node.js or browser globals to decide which code path
|
|
232
|
+
to use. In `mini_racer`, neither environment is detected. You may need to
|
|
233
|
+
configure your bundler to alias server-friendly versions. For example, in
|
|
234
|
+
esbuild:
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
// build_ssr.mjs
|
|
238
|
+
await esbuild.build({
|
|
239
|
+
// ...
|
|
240
|
+
alias: {
|
|
241
|
+
'html-dom-parser': 'html-dom-parser/lib/html-to-dom-server'
|
|
221
242
|
}
|
|
222
|
-
|
|
243
|
+
})
|
|
223
244
|
```
|
|
224
245
|
|
|
225
246
|
## Writing universal code
|
|
@@ -251,39 +272,16 @@ moving the `require` to `useEffect` in your component.
|
|
|
251
272
|
## Polyfills
|
|
252
273
|
|
|
253
274
|
React SSR may import node.js dependencies that you need to polyfill for. See
|
|
254
|
-
a sample esbuild [build script](./sample/
|
|
275
|
+
a sample esbuild [build script](./sample/build.mjs) and a [shim.js](./sample/shim.js)
|
|
255
276
|
to get around these issues.
|
|
256
277
|
|
|
257
|
-
## Testing
|
|
258
|
-
|
|
259
|
-
When running in test environments that also forks, you may need to set up new mini_racer
|
|
260
|
-
contexts for each parallel worker. For example:
|
|
261
|
-
|
|
262
|
-
```ruby
|
|
263
|
-
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
|
264
|
-
include ActionView::Helpers::TranslationHelper
|
|
265
|
-
include Devise::Test::IntegrationHelpers
|
|
266
|
-
|
|
267
|
-
parallelize_setup do
|
|
268
|
-
MINI_RACER_CONTEXT.dispose if defined?(MINI_RACER_CONTEXT)
|
|
269
|
-
ctx = MiniRacer::Context.new(timeout: 1000, ensure_gc_after_idle: 2000)
|
|
270
|
-
Object.send(:remove_const, :MINI_RACER_CONTEXT) if defined?(MINI_RACER_CONTEXT)
|
|
271
|
-
Object.const_set(:MINI_RACER_CONTEXT, Humid.prepare(ctx))
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
parallelize_teardown do
|
|
275
|
-
MINI_RACER_CONTEXT.dispose if defined?(MINI_RACER_CONTEXT)
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
```
|
|
279
|
-
|
|
280
278
|
## Telemetry
|
|
281
279
|
|
|
282
280
|
The `MiniRacer::Context` gives you access to V8 heap statistics for monitoring
|
|
283
281
|
memory usage over time.
|
|
284
282
|
|
|
285
283
|
```ruby
|
|
286
|
-
|
|
284
|
+
MINI_RACER_SSR[:context].heap_stats
|
|
287
285
|
# {:total_heap_size=>3100672,
|
|
288
286
|
# :total_heap_size_executable=>4194304,
|
|
289
287
|
# :total_physical_size=>1280640,
|
|
@@ -302,7 +300,7 @@ render_histogram = meter.create_histogram("humid.render.duration", unit: "ms", d
|
|
|
302
300
|
heap_gauge = meter.create_gauge("humid.heap.used_bytes", unit: "By", description: "V8 heap used bytes")
|
|
303
301
|
|
|
304
302
|
ActiveSupport::Notifications.subscribe("render.humid") do |event|
|
|
305
|
-
stats =
|
|
303
|
+
stats = MINI_RACER_SSR[:context].heap_stats
|
|
306
304
|
attributes = { "worker.pid" => Process.pid.to_s }
|
|
307
305
|
|
|
308
306
|
render_histogram.record(event.duration, attributes: attributes)
|
|
@@ -313,13 +311,14 @@ end
|
|
|
313
311
|
A steadily climbing `used_heap_size` across requests indicates a memory leak in
|
|
314
312
|
your JavaScript bundle.
|
|
315
313
|
|
|
314
|
+
|
|
316
315
|
## Contributing
|
|
317
316
|
|
|
318
317
|
Please see [CONTRIBUTING.md](/CONTRIBUTING.md).
|
|
319
318
|
|
|
320
319
|
## License
|
|
321
320
|
|
|
322
|
-
Humid is Copyright © 2021-
|
|
321
|
+
Humid is Copyright © 2021-2026 Johny Ho.
|
|
323
322
|
It is free software, and may be redistributed under the terms specified in the
|
|
324
323
|
[LICENSE](/LICENSE.md) file.
|
|
325
324
|
|
|
@@ -338,9 +337,8 @@ We are [available for hire][hire].
|
|
|
338
337
|
[community]: https://thoughtbot.com/community?utm_source=github
|
|
339
338
|
[hire]: https://thoughtbot.com/hire-us?utm_source=github
|
|
340
339
|
|
|
341
|
-
|
|
342
340
|
<!-- END /templates/footer.md -->
|
|
343
341
|
|
|
344
342
|
[mini_racer]: https://github.com/rubyjs/mini_racer
|
|
345
343
|
[vue_ssr]: https://ssr.vuejs.org/
|
|
346
|
-
[sample]: ./
|
|
344
|
+
[sample]: ./sample/
|
data/lib/humid/version.rb
CHANGED
data/lib/humid.rb
CHANGED
|
@@ -30,6 +30,8 @@ module Humid
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def prepare(ctx, options = {})
|
|
33
|
+
return ctx if ctx.respond_to?(:humid_prepared?) && ctx.humid_prepared?
|
|
34
|
+
|
|
33
35
|
effective_config = config.merge(options)
|
|
34
36
|
logger = effective_config.logger
|
|
35
37
|
log_formatter = effective_config.log_formatter
|