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 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