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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -67
  3. data/lib/humid/version.rb +1 -1
  4. data/lib/humid.rb +2 -0
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 961eafadcfe1132cdd132c096a28aba48155c740b224c3cbc32b4fd9731c10a6
4
- data.tar.gz: 8a3635e896a4915c508a096c3b9f60e7d51265b39c6c448150fb89a627a3ab06
3
+ metadata.gz: f8a07ab8d934750bbdb01dc4596426d02edd7733d7bf87093b8ca36d5abbbb33
4
+ data.tar.gz: d3c9f28d92d637d8d4eb20e78676a0eacf09d7c922c0583448f3aacc1befe4fa
5
5
  SHA512:
6
- metadata.gz: 7f9f13d45e1b4023cccdc88300c151024dbb08a5bcc73c24b1a81e089f1ad1d2a4ec1faea12feb81e13949e2c423a8e8a392d73bf45b547ecdcd20a6462b74b6
7
- data.tar.gz: fba2e9ea74fdeab8a90f5503a0b34cf977ddb0006dcaf234ceff8b1d06548079461e0e5d17466cace1c68937b7fa290a5823ef0fe01352886b545b0fe87c9cc2
6
+ metadata.gz: 311cdf7125016802906bc28b7545c80c22e01709ebe679ead307f68783bab051a9e30bc634b777ce41802ad9d6564288305c593aee5da05a40e853b8a7ce31f2
7
+ data.tar.gz: 43777369d6c7b2525957d11117be0b1df56e960dbea0ca7be822ebb1b0d7c1e9af5f406fea47619d7f50829e203f610fb1074b1435b6ccce310453f1db04bf05
data/README.md CHANGED
@@ -1,4 +1,9 @@
1
- # Humid
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
  ![Build Status](https://github.com/thoughtbot/humid/actions/workflows/build.yml/badge.svg?branch=main)
4
9
 
@@ -12,16 +17,20 @@ returns an HTML string.
12
17
 
13
18
  ## Design
14
19
 
15
- Humid is designed for the common case where all data is gathered before
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
- ## Caution
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
- This project is in its early phases of development. Its interface,
23
- behavior, and name are likely to change drastically before a major version
24
- release.
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
- # app/initializers/humid.rb
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('app', 'assets', 'builds', 'server_rendering.js')
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('app', 'assets', 'builds', 'server_rendering.js.map')
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 out to Rails log and Humid.render will return an empty string
70
+ # logged and Humid.render will return an empty string.
62
71
  #
63
72
  # Defaults to true.
64
- config.raise_render_errors = Rails.env.development? || Rails.env.test?
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 Spring and other forked envs.
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
- ctx = MiniRacer::Context.new(timeout: 100, ensure_gc_after_idle: 2000)
78
- MINI_RACER_CONTEXT = Humid.prepare(ctx)
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 a
121
- `MINI_RACER_CONTEXT` with options of your choosing on worker boot. **There
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: 100, ensure_gc_after_idle: 2000)
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
- MINI_RACER_CONTEXT.dispose
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
- MINI_RACER_CONTEXT = Humid.prepare(
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
- See the [sample server_rendering.tsx](./sample/server_rendering.tsx) to see how
153
- it is integrated.
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(MINI_RACER_CONTEXT, json).html_safe %>
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
- You may need webpacker to create aliases for server friendly libraries that can
213
- not detect the `mini_racer` environment. For example, in `webpack.config.js`.
214
-
215
- ```diff
216
- ...
217
- resolve: {
218
- alias: {
219
- 'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')
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/bulid_ssr.js) and a [shim.js](./sample/shim.js)
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
- MINI_RACER_CONTEXT.heap_stats
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 = MINI_RACER_CONTEXT.heap_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-2024 Johny Ho.
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]: ./webpack.config.js
344
+ [sample]: ./sample/
data/lib/humid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Humid
2
- VERSION = "0.6.0".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: humid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johny Ho