humid 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|