humid 0.0.4 → 0.0.5
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 +95 -46
- data/lib/humid.rb +28 -8
- data/lib/humid/version.rb +1 -1
- data/spec/log_subscriber_spec.rb +1 -1
- data/spec/render_spec.rb +43 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a783b726d5542a0abfc94fc1918aad0212c13ac7b6db8b8efd90c5452a222b2e
|
4
|
+
data.tar.gz: b9c3719ace7b00d210c992b48f9c4ee02010e81d19c30aa47e8bf6fdd9e9373b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d29027f962022c6f8d5aeaf09c11730d572a32f8936e025fc04c3490921ac51468f6567e99f29aeb090a344150fa5edce2bbe14e83c18bfe9afc62e89fb34a87
|
7
|
+
data.tar.gz: 9ceb09c4bebef88f71f3b9c229c9317526a1d5cd5100dce4a270aad383334401a14baa7e108417170c5c3cad122523e9539733404d4c9a3cdf6f7bb8c2ec5dbf
|
data/README.md
CHANGED
@@ -34,20 +34,33 @@ Add an initializer to configure
|
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
Humid.configure do |config|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
#
|
37
|
+
# Name of your webpacker pack file located in `app/javascript/packs/`. You
|
38
|
+
# should use a separate pack from your `application.js`.
|
39
|
+
#
|
40
|
+
# Defaults to "server_rendering.js"
|
41
|
+
config.server_rendering_pack = "server_rendering.js"
|
42
|
+
|
43
|
+
# Name of your webpacker pack source map.
|
44
|
+
#
|
45
|
+
# Defaults to `false`
|
41
46
|
config.use_source_map = true
|
42
47
|
|
43
|
-
#
|
48
|
+
# Raise errors if JS rendering failed. If false, the error will be
|
49
|
+
# logged out to Rails log and Humid.render will return an empty string
|
50
|
+
#
|
51
|
+
# Defaults to true.
|
52
|
+
config.raise_render_errors = Rails.env.development? || Rails.env.test?
|
53
|
+
|
54
|
+
# The logger instance.
|
44
55
|
# `console.log` and friends (`warn`, `error`) are delegated to
|
45
56
|
# the respective logger levels on the ruby side.
|
57
|
+
#
|
58
|
+
# Defaults to `Logger.new(STDOUT)`
|
46
59
|
config.logger = Rails.logger
|
47
60
|
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
61
|
+
# Options passed to mini_racer.
|
62
|
+
#
|
63
|
+
# Defaults to empty `{}`.
|
51
64
|
config.context_options = {
|
52
65
|
timeout: 1000,
|
53
66
|
ensure_gc_after_idle: 2000
|
@@ -55,11 +68,13 @@ Humid.configure do |config|
|
|
55
68
|
end
|
56
69
|
|
57
70
|
# Common development options
|
58
|
-
|
59
|
-
#
|
60
|
-
|
61
|
-
|
62
|
-
#
|
71
|
+
if Rails.env.development? || Rails.env.test?
|
72
|
+
# Use single_threaded mode for Spring and other forked envs.
|
73
|
+
MiniRacer::Platform.set_flags! :single_threaded
|
74
|
+
|
75
|
+
# If you're using Puma in single mode:
|
76
|
+
Humid.create_context
|
77
|
+
end
|
63
78
|
```
|
64
79
|
|
65
80
|
If you'd like support for source map support, you will need to
|
@@ -95,46 +110,16 @@ The following functions are **not** available in the mini_racer environment
|
|
95
110
|
`console.log` and friends (`info`, `error`, `warn`) are delegated to the
|
96
111
|
respective methods on the configured logger.
|
97
112
|
|
98
|
-
### Webpacker
|
99
|
-
You may need webpacker to create aliases for server friendly libraries that can
|
100
|
-
not detect the `mini_racer` environment.
|
101
|
-
|
102
|
-
```diff
|
103
|
-
// config/webpack/development.js
|
104
|
-
|
105
|
-
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
106
|
-
|
107
|
-
const environment = require('./environment')
|
108
|
-
+const path = require('path')
|
109
|
-
+const ConfigObject = require('@rails/webpacker/package/config_types/config
|
110
|
-
|
111
|
-
-module.exports = environment.toWebpackConfig()
|
112
|
-
+const webConfig = environment.toWebpackConfig()
|
113
|
-
+const ssrConfig = new ConfigObject(webConfig.toObject())
|
114
|
-
+
|
115
|
-
+ssrConfig.delete('entry')
|
116
|
-
+ssrConfig.merge({
|
117
|
-
+ entry: {
|
118
|
-
+ server_rendering: webConfig.entry.server_rendering
|
119
|
-
+ },
|
120
|
-
+ resolve: {
|
121
|
-
+ alias: {
|
122
|
-
+ 'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')
|
123
|
-
+ }
|
124
|
-
+ }
|
125
|
-
+})
|
126
|
-
+
|
127
|
-
+delete webConfig.entry.server_rendering
|
128
|
-
+module.exports = [ssrConfig, webConfig]
|
129
|
-
```
|
130
|
-
|
131
113
|
## Usage
|
132
114
|
|
133
115
|
Pass your HTML render function to `setHumidRenderer`
|
134
116
|
|
135
117
|
```javascript
|
118
|
+
// Set a factory function that will create a new instance of our app
|
119
|
+
// for each request.
|
136
120
|
setHumidRenderer((json) => {
|
137
121
|
const initialState = JSON.parse(json)
|
122
|
+
|
138
123
|
return ReactDOMServer.renderToString(
|
139
124
|
<Application initialPage={initialState}/>
|
140
125
|
)
|
@@ -169,6 +154,69 @@ on_worker_shutdown do
|
|
169
154
|
end
|
170
155
|
```
|
171
156
|
|
157
|
+
### Server-side libraries that detect node.js envs.
|
158
|
+
You may need webpacker to create aliases for server friendly libraries that can
|
159
|
+
not detect the `mini_racer` environment.
|
160
|
+
|
161
|
+
```diff
|
162
|
+
// config/webpack/production.js
|
163
|
+
// config/webpack/development.js
|
164
|
+
// config/webpack/test.js
|
165
|
+
|
166
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
167
|
+
|
168
|
+
const environment = require('./environment')
|
169
|
+
+const path = require('path')
|
170
|
+
+const ConfigObject = require('@rails/webpacker/package/config_types/config
|
171
|
+
|
172
|
+
-module.exports = environment.toWebpackConfig()
|
173
|
+
+const webConfig = environment.toWebpackConfig()
|
174
|
+
+const ssrConfig = new ConfigObject(webConfig.toObject())
|
175
|
+
+
|
176
|
+
+ssrConfig.delete('entry')
|
177
|
+
+ssrConfig.merge({
|
178
|
+
+ entry: {
|
179
|
+
+ server_rendering: webConfig.entry.server_rendering
|
180
|
+
+ },
|
181
|
+
+ resolve: {
|
182
|
+
+ alias: {
|
183
|
+
+ 'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')
|
184
|
+
+ }
|
185
|
+
+ }
|
186
|
+
+})
|
187
|
+
+
|
188
|
+
+delete webConfig.entry.server_rendering
|
189
|
+
+module.exports = [ssrConfig, webConfig]
|
190
|
+
```
|
191
|
+
|
192
|
+
## Writing universal code
|
193
|
+
[Vue has an amazing resource][vue_ssr] on how to write universal code. Below
|
194
|
+
are a few highlights that are important to keep in mind.
|
195
|
+
|
196
|
+
### State
|
197
|
+
|
198
|
+
Humid uses a single context across multiple request. To avoid state pollution, we
|
199
|
+
provide a factory function to `setHumidRenderer` that builds a new app instance on
|
200
|
+
every call.
|
201
|
+
|
202
|
+
This provides better isolation, but as it is still a shared context, polluting
|
203
|
+
`global` is still possible. Be careful of modifying `global` in your code.
|
204
|
+
|
205
|
+
### Polyfills
|
206
|
+
|
207
|
+
Polyfills will fail when using in the `mini_racer` environment because of missing
|
208
|
+
browser APIs. Account for this by moving the `require` to `componentDidMount`
|
209
|
+
in your component.
|
210
|
+
|
211
|
+
```
|
212
|
+
componentDidMount() {
|
213
|
+
const dialogPolyfill = require('dialog-polyfill').default
|
214
|
+
dialogPolyfill.registerDialog(this.dialog.current)
|
215
|
+
this.dialog.current.open = this.props.open
|
216
|
+
this.dialog.current.showModal()
|
217
|
+
}
|
218
|
+
```
|
219
|
+
|
172
220
|
## Contributing
|
173
221
|
|
174
222
|
Please see [CONTRIBUTING.md](/CONTRIBUTING.md).
|
@@ -194,3 +242,4 @@ See [our other projects][community] or
|
|
194
242
|
[hire]: https://thoughtbot.com?utm_source=github
|
195
243
|
[mini_racer]: https://github.com/rubyjs/mini_racer
|
196
244
|
[webpacker]: https://github.com/rails/webpacker
|
245
|
+
[vue_ssr]: https://ssr.vuejs.org/
|
data/lib/humid.rb
CHANGED
@@ -14,7 +14,12 @@ module Humid
|
|
14
14
|
class RenderError < StandardError
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
class FileNotFound < StandardError
|
18
|
+
end
|
19
|
+
|
20
|
+
@@context = nil
|
21
|
+
|
22
|
+
config_accessor :server_rendering_pack do
|
18
23
|
"server_rendering.js"
|
19
24
|
end
|
20
25
|
|
@@ -22,6 +27,10 @@ module Humid
|
|
22
27
|
false
|
23
28
|
end
|
24
29
|
|
30
|
+
config_accessor :raise_render_errors do
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
25
34
|
config_accessor :logger do
|
26
35
|
Logger.new(STDOUT)
|
27
36
|
end
|
@@ -60,8 +69,8 @@ module Humid
|
|
60
69
|
end
|
61
70
|
|
62
71
|
public_path = Webpacker.config.public_path
|
63
|
-
|
64
|
-
source_path = public_path.join(Webpacker.manifest.lookup(
|
72
|
+
server_rendering_pack = config.server_rendering_pack
|
73
|
+
source_path = public_path.join(Webpacker.manifest.lookup(server_rendering_pack)[1..-1])
|
65
74
|
filename = File.basename(source_path.to_s)
|
66
75
|
|
67
76
|
if @@current_filename != filename
|
@@ -98,15 +107,19 @@ module Humid
|
|
98
107
|
ctx.eval(js)
|
99
108
|
|
100
109
|
public_path = Webpacker.config.public_path
|
101
|
-
server_rendering_file = config.server_rendering_file
|
102
|
-
server_rendering_map = "#{config.server_rendering_file}.map"
|
103
110
|
|
104
|
-
|
105
|
-
|
111
|
+
webpack_source_file = Webpacker.manifest.lookup(config.server_rendering_pack)
|
112
|
+
if webpack_source_file.nil?
|
113
|
+
raise FileNotFound.new("Humid could not find a built pack for #{config.server_rendering_pack}")
|
114
|
+
end
|
115
|
+
|
106
116
|
if config.use_source_map
|
117
|
+
webpack_source_map = Webpacker.manifest.lookup("#{config.server_rendering_pack}.map")
|
118
|
+
map_path = public_path.join(webpack_source_map[1..-1])
|
107
119
|
ctx.attach("readSourceMap", proc { File.read(map_path) })
|
108
120
|
end
|
109
121
|
|
122
|
+
source_path = public_path.join(webpack_source_file[1..-1])
|
110
123
|
filename = File.basename(source_path.to_s)
|
111
124
|
@@current_filename = filename
|
112
125
|
ctx.eval(File.read(source_path), filename: filename)
|
@@ -119,7 +132,14 @@ module Humid
|
|
119
132
|
context.call("__renderer", *args)
|
120
133
|
rescue MiniRacer::RuntimeError => e
|
121
134
|
message = ([e.message] + e.backtrace.filter {|x| x.starts_with? "JavaScript"}).join("\n")
|
122
|
-
|
135
|
+
render_error = Humid::RenderError.new(message)
|
136
|
+
|
137
|
+
if config.raise_render_errors
|
138
|
+
raise render_error
|
139
|
+
else
|
140
|
+
config.logger.error(render_error.inspect)
|
141
|
+
""
|
142
|
+
end
|
123
143
|
end
|
124
144
|
end
|
125
145
|
end
|
data/lib/humid/version.rb
CHANGED
data/spec/log_subscriber_spec.rb
CHANGED
@@ -45,7 +45,7 @@ RSpec.describe Humid::LogSubscriber do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it "is attached" do
|
48
|
-
allow(Humid.config).to receive("
|
48
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
49
49
|
Humid.create_context
|
50
50
|
expect(Humid::LogSubscriber.runtime).to eql(0)
|
51
51
|
Humid.render
|
data/spec/render_spec.rb
CHANGED
@@ -14,14 +14,24 @@ RSpec.describe "Humid" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "creates a context with initial js" do
|
17
|
-
allow(Humid.config).to receive("
|
17
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
18
18
|
Humid.create_context
|
19
19
|
|
20
20
|
expect(Humid.context).to be_kind_of(MiniRacer::Context)
|
21
21
|
end
|
22
22
|
|
23
|
+
context "When the file can not be found" do
|
24
|
+
it "raises" do
|
25
|
+
allow(Humid.config).to receive("server_rendering_pack") { "does_not_exist.js" }
|
26
|
+
|
27
|
+
expect {
|
28
|
+
Humid.create_context
|
29
|
+
}.to raise_error(Humid::FileNotFound, "Humid could not find a built pack for does_not_exist.js")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
23
33
|
it "does not have timeouts, immediates, and intervals" do
|
24
|
-
allow(Humid.config).to receive("
|
34
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
25
35
|
|
26
36
|
Humid.create_context
|
27
37
|
|
@@ -43,7 +53,7 @@ RSpec.describe "Humid" do
|
|
43
53
|
end
|
44
54
|
|
45
55
|
it "proxies to Rails logger" do
|
46
|
-
allow(Humid.config).to receive("
|
56
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
47
57
|
Humid.create_context
|
48
58
|
expect(Humid.logger).to receive(:info).with("hello")
|
49
59
|
|
@@ -53,7 +63,7 @@ RSpec.describe "Humid" do
|
|
53
63
|
|
54
64
|
describe "context" do
|
55
65
|
it "returns the created context" do
|
56
|
-
allow(Humid.config).to receive("
|
66
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
57
67
|
|
58
68
|
Humid.create_context
|
59
69
|
|
@@ -64,7 +74,7 @@ RSpec.describe "Humid" do
|
|
64
74
|
it "does not recompile the JS" do
|
65
75
|
allow(Webpacker).to receive_message_chain("env.development?") { false }
|
66
76
|
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
67
|
-
allow(Humid.config).to receive("
|
77
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
68
78
|
|
69
79
|
Humid.create_context
|
70
80
|
prev_context = Humid.context
|
@@ -84,7 +94,7 @@ RSpec.describe "Humid" do
|
|
84
94
|
allow(Webpacker).to receive_message_chain("env.development?") { true }
|
85
95
|
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
86
96
|
allow(Webpacker).to receive_message_chain("compiler.compile")
|
87
|
-
allow(Humid.config).to receive("
|
97
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
88
98
|
|
89
99
|
Humid.create_context
|
90
100
|
prev_context = Humid.context
|
@@ -92,7 +102,7 @@ RSpec.describe "Humid" do
|
|
92
102
|
|
93
103
|
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
94
104
|
# This simulates a changing file
|
95
|
-
allow(Humid.config).to receive("
|
105
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple_changed.js" }
|
96
106
|
|
97
107
|
next_context = Humid.context
|
98
108
|
|
@@ -104,7 +114,7 @@ RSpec.describe "Humid" do
|
|
104
114
|
allow(Webpacker).to receive_message_chain("env.development?") { true }
|
105
115
|
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
106
116
|
allow(Webpacker).to receive_message_chain("compiler.compile")
|
107
|
-
allow(Humid.config).to receive("
|
117
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
108
118
|
|
109
119
|
Humid.create_context
|
110
120
|
prev_context = Humid.context
|
@@ -113,7 +123,7 @@ RSpec.describe "Humid" do
|
|
113
123
|
|
114
124
|
allow(Webpacker).to receive_message_chain("compiler.stale?") { false }
|
115
125
|
# This simulates a changing file
|
116
|
-
allow(Humid.config).to receive("
|
126
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple_changed.js" }
|
117
127
|
|
118
128
|
next_context = Humid.context
|
119
129
|
|
@@ -126,14 +136,14 @@ RSpec.describe "Humid" do
|
|
126
136
|
|
127
137
|
describe "render" do
|
128
138
|
it "returns a js output" do
|
129
|
-
allow(Humid.config).to receive("
|
139
|
+
allow(Humid.config).to receive("server_rendering_pack") { "simple.js" }
|
130
140
|
Humid.create_context
|
131
141
|
|
132
142
|
expect(Humid.render).to eql("hello")
|
133
143
|
end
|
134
144
|
|
135
145
|
it "applys args to the func" do
|
136
|
-
allow(Humid.config).to receive("
|
146
|
+
allow(Humid.config).to receive("server_rendering_pack") { "args.js" }
|
137
147
|
Humid.create_context
|
138
148
|
|
139
149
|
args = ["a", 1, 2, [], {}]
|
@@ -142,7 +152,7 @@ RSpec.describe "Humid" do
|
|
142
152
|
end
|
143
153
|
|
144
154
|
it "can use source maps to see errors" do
|
145
|
-
allow(Humid.config).to receive("
|
155
|
+
allow(Humid.config).to receive("server_rendering_pack") { "reporting.js" }
|
146
156
|
allow(Humid.config).to receive("use_source_map") { true }
|
147
157
|
|
148
158
|
Humid.create_context
|
@@ -151,12 +161,28 @@ RSpec.describe "Humid" do
|
|
151
161
|
Humid.render
|
152
162
|
}.to raise_error { |error|
|
153
163
|
expect(error).to be_a(Humid::RenderError)
|
154
|
-
message =
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
164
|
+
message = <<~MSG
|
165
|
+
Error: ^^ Look! These stack traces map to the actual source code :)
|
166
|
+
JavaScript at throwSomeError (/webpack:/app/javascript/packs/components/error-causing-component.js:2:1)
|
167
|
+
JavaScript at ErrorCausingComponent (/webpack:/app/javascript/packs/components/error-causing-component.js:8:1)
|
168
|
+
JavaScript at /webpack:/app/javascript/packs/reporting.js:18:1
|
169
|
+
MSG
|
170
|
+
|
171
|
+
expect(error.message).to eql message.strip
|
159
172
|
}
|
160
173
|
end
|
174
|
+
|
175
|
+
it "siliences render errors to the log" do
|
176
|
+
allow(Humid.config).to receive("server_rendering_pack") { "reporting.js" }
|
177
|
+
allow(Humid.config).to receive("raise_render_errors") { false }
|
178
|
+
allow(Humid.config).to receive("use_source_map") { true }
|
179
|
+
|
180
|
+
Humid.create_context
|
181
|
+
|
182
|
+
expect(Humid.logger).to receive(:error)
|
183
|
+
output = Humid.render
|
184
|
+
|
185
|
+
expect(output).to eql("")
|
186
|
+
end
|
161
187
|
end
|
162
188
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: humid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johny Ho
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webpacker
|