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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64ab68e5648b4211e7d39b272da5f94e1aaf3bfcdf625db30ee5f6c72a7dc529
4
- data.tar.gz: 251e41301a91ea534547caa84b76ffef68b463299fd012c39b2b26e4626b6d13
3
+ metadata.gz: a783b726d5542a0abfc94fc1918aad0212c13ac7b6db8b8efd90c5452a222b2e
4
+ data.tar.gz: b9c3719ace7b00d210c992b48f9c4ee02010e81d19c30aa47e8bf6fdd9e9373b
5
5
  SHA512:
6
- metadata.gz: f97030ff349d70d7b4605969953194c34b8012dc12f477aa8c5f6f1ccdfee88be2ccb5c495fc880378be03c381ed88e11c8453abd1d8a92ad3621aad34a0b553
7
- data.tar.gz: 23f59abc3c56fe9d11b6084e89b0c02a3b11c4e12175bcab6ea4a641630616950b6943a9948c64be270173461f383a540fd570fdb69fd439cfcd7007d6e542ea
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
- # name of your webpacker pack. Defaults to "server_rendering.js"
38
- config.server_rendering_source = "server_rendering.js"
39
-
40
- # name of your webpacker pack source map. Defaults to `false`
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
- # The logger instance. Defaults to `Logger.new(STDOUT)`
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
- # context_options. Options passed to mini_racer. Defaults to
49
- # empty.
50
- # config.context_options = {}
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
- # You may need to use single_threaded mode with Spring
59
- # MiniRacer::Platform.set_flags! :single_threaded
60
- #
61
- # If you're using Puma in single mode:
62
- # Humid.create_context
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
- config_accessor :server_rendering_file do
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
- server_rendering_file = config.server_rendering_file
64
- source_path = public_path.join(Webpacker.manifest.lookup(server_rendering_file)[1..-1])
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
- source_path = public_path.join(Webpacker.manifest.lookup(server_rendering_file)[1..-1])
105
- map_path = public_path.join(Webpacker.manifest.lookup(server_rendering_map)[1..-1])
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
- raise Humid::RenderError.new(message)
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
@@ -1,3 +1,3 @@
1
1
  module Humid
2
- VERSION = "0.0.4".freeze
2
+ VERSION = "0.0.5".freeze
3
3
  end
@@ -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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple_changed.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "simple_changed.js" }
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("server_rendering_file") { "simple.js" }
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("server_rendering_file") { "args.js" }
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("server_rendering_file") { "reporting.js" }
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 = error.message.split("\n")
155
- expect(message[0]).to eql("Error: ^^ Look! These stack traces map to the actual source code :)")
156
- expect(message[1]).to eql("JavaScript at throwSomeError (/webpack:/app/javascript/packs/components/error-causing-component.js:2:1)")
157
- expect(message[2]).to eql("JavaScript at ErrorCausingComponent (/webpack:/app/javascript/packs/components/error-causing-component.js:8:1)")
158
- expect(message[3]).to eql("JavaScript at /webpack:/app/javascript/packs/reporting.js:18:1")
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
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-23 00:00:00.000000000 Z
11
+ date: 2021-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: webpacker