humid 0.0.1
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 +7 -0
- data/README.md +179 -0
- data/lib/humid.rb +109 -0
- data/lib/humid/controller_runtime.rb +41 -0
- data/lib/humid/log_subscriber.rb +22 -0
- data/lib/humid/version.rb +3 -0
- data/spec/controller_runtime_spec.rb +79 -0
- data/spec/log_subscriber_spec.rb +54 -0
- data/spec/render_spec.rb +139 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 331e268f4bfc9f9b46e4246a9fb1af56245616bedecfb13a9b220040fca74636
|
4
|
+
data.tar.gz: 87631778cddbd5511202a0a3aaaa54fb6827b8aee8bdae29f80297ee6764cd55
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5161834e3f6b0a8d6cb9e991965df392491e204373c0ec54773cf114f8c489be88f435a5d6ba90c226dc6a698ea053ca3ccaf64581cb01399272057ecb600990
|
7
|
+
data.tar.gz: a545a0ffb5c7f1dfdf333bb960566a28fb355fd3dfc60ede7ed88f3210f507ca21e7b389138c07b2a773903110df66b7e60df844a57815c0a87fb624a15ee44c
|
data/README.md
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
# Humid
|
2
|
+
|
3
|
+
Humid is a lightweight helper that leans on [mini_racer] and [webpacker] to
|
4
|
+
generate Server Side Rendered (SSR) pages from your javascript application.
|
5
|
+
|
6
|
+
[](https://circleci.com/gh/thoughtbot/humid)
|
8
|
+
|
9
|
+
## Caution
|
10
|
+
|
11
|
+
This project is in its early phases of development. Its interface,
|
12
|
+
behavior, and name are likely to change drastically before a major version
|
13
|
+
release.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add Humid to your Gemfile.
|
18
|
+
|
19
|
+
```
|
20
|
+
gem 'humid'
|
21
|
+
```
|
22
|
+
|
23
|
+
For source-map support, also add
|
24
|
+
|
25
|
+
```
|
26
|
+
yarn add source-map-support
|
27
|
+
```
|
28
|
+
|
29
|
+
|
30
|
+
## Configuration
|
31
|
+
|
32
|
+
Add an initializer to configure
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Humid.configure do |config|
|
36
|
+
# name of your webpacker pack. Defaults to "server_rendering.js"
|
37
|
+
config.server_rendering_source = "server_rendering.js"
|
38
|
+
|
39
|
+
# name of your webpacker pack source map. Defaults to `nil`
|
40
|
+
config.server_rendering_source_map = "server_rendering.js.map"
|
41
|
+
|
42
|
+
# The logger instance. Defaults to `Logger.new(STDOUT)`
|
43
|
+
# `console.log` and friends (`warn`, `error`) are delegated to
|
44
|
+
# the respective logger levels on the ruby side.
|
45
|
+
config.logger = Rails.logger
|
46
|
+
|
47
|
+
# context_options. Options passed to mini_racer. Defaults to
|
48
|
+
# config.context_options = {
|
49
|
+
# timeout: 1000,
|
50
|
+
# ensure_gc_after_idle: 2000
|
51
|
+
# }
|
52
|
+
end
|
53
|
+
|
54
|
+
# If using puma in single mode
|
55
|
+
# Humid.create_context
|
56
|
+
```
|
57
|
+
|
58
|
+
If you'd like support for source map support, you will need to
|
59
|
+
1. Ensure `config.server_rendering_source_map` has a value
|
60
|
+
2. Add the following to your `server_rendering.js` pack.
|
61
|
+
|
62
|
+
```javascript
|
63
|
+
require("source-map-support").install({
|
64
|
+
retrieveSourceMap: filename => {
|
65
|
+
return {
|
66
|
+
url: filename,
|
67
|
+
map: readSourceMap(filename)
|
68
|
+
};
|
69
|
+
}
|
70
|
+
});
|
71
|
+
```
|
72
|
+
|
73
|
+
## The mini_racer environment.
|
74
|
+
|
75
|
+
The following functions are **not** available in the mini_racer environment
|
76
|
+
|
77
|
+
- `setTimeout`
|
78
|
+
- `clearTimeout`
|
79
|
+
- `setInterval`
|
80
|
+
- `clearInterval`
|
81
|
+
- `setImmediate`
|
82
|
+
- `clearImmediate`
|
83
|
+
|
84
|
+
### `console.log`
|
85
|
+
|
86
|
+
`console.log` and friends (`info`, `error`, `warn`) are delegated to the
|
87
|
+
respective methods on the configured logger.
|
88
|
+
|
89
|
+
### Webpacker
|
90
|
+
You may need webpacker to create aliases for server friendly libraries that can
|
91
|
+
not detect the `mini_racer` environment.
|
92
|
+
|
93
|
+
```diff
|
94
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
95
|
+
|
96
|
+
const environment = require('./environment')
|
97
|
+
+const path = require('path')
|
98
|
+
+const ConfigObject = require('@rails/webpacker/package/config_types/config
|
99
|
+
|
100
|
+
-module.exports = environment.toWebpackConfig()
|
101
|
+
+const webConfig = environment.toWebpackConfig()
|
102
|
+
+const ssrConfig = new ConfigObject(webConfig.toObject())
|
103
|
+
+
|
104
|
+
+ssrConfig.delete('entry')
|
105
|
+
+ssrConfig.merge({
|
106
|
+
+ entry: {
|
107
|
+
+ server_rendering: webConfig.entry.server_rendering
|
108
|
+
+ },
|
109
|
+
+ resolve: {
|
110
|
+
+ alias: {
|
111
|
+
+ 'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')
|
112
|
+
+ }
|
113
|
+
+ }
|
114
|
+
+})
|
115
|
+
+
|
116
|
+
+delete webConfig.entry.server_rendering
|
117
|
+
+module.exports = [ssrConfig, webConfig]
|
118
|
+
```
|
119
|
+
|
120
|
+
## Usage
|
121
|
+
|
122
|
+
Pass your HTML render function to `setHumidRenderer`
|
123
|
+
|
124
|
+
```javascript
|
125
|
+
setHumidRenderer((json) => {
|
126
|
+
const initialState = JSON.parse(json)
|
127
|
+
return ReactDOMServer.renderToString(
|
128
|
+
<Application initialPage={initialState}/>
|
129
|
+
)
|
130
|
+
})
|
131
|
+
```
|
132
|
+
|
133
|
+
And finally call `render` from ERB.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
<%= Humid.render(initial_state) %>
|
137
|
+
```
|
138
|
+
|
139
|
+
### Puma
|
140
|
+
|
141
|
+
`mini_racer` is thread safe, but not fork safe. To use with web servers that
|
142
|
+
employ forking, use `Humid.create_context` only on forked processes.
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
# Puma
|
146
|
+
on_worker_boot do
|
147
|
+
Humid.create_context
|
148
|
+
end
|
149
|
+
|
150
|
+
on_worker_shutdown do
|
151
|
+
Humid.dispose
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
Please see [CONTRIBUTING.md](/CONTRIBUTING.md).
|
158
|
+
|
159
|
+
## License
|
160
|
+
|
161
|
+
Humid is Copyright © 2021-2021 Johny Ho.
|
162
|
+
It is free software, and may be redistributed under the terms specified in the
|
163
|
+
[LICENSE](/LICENSE.md) file.
|
164
|
+
|
165
|
+
## About thoughtbot
|
166
|
+
|
167
|
+

|
168
|
+
|
169
|
+
Humid is maintained and funded by thoughtbot, inc.
|
170
|
+
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
171
|
+
|
172
|
+
We love open source software!
|
173
|
+
See [our other projects][community] or
|
174
|
+
[hire us][hire] to design, develop, and grow your product.
|
175
|
+
|
176
|
+
[community]: https://thoughtbot.com/community?utm_source=github
|
177
|
+
[hire]: https://thoughtbot.com?utm_source=github
|
178
|
+
[mini_racer]: https://github.com/rubyjs/mini_racer
|
179
|
+
[webpacker]: https://github.com/rails/webpacker
|
data/lib/humid.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require "mini_racer"
|
2
|
+
require "logger"
|
3
|
+
require "webpacker"
|
4
|
+
require "active_support"
|
5
|
+
require "active_support/core_ext"
|
6
|
+
require "humid/log_subscriber"
|
7
|
+
require "humid/controller_runtime"
|
8
|
+
require "humid/version"
|
9
|
+
|
10
|
+
module Humid
|
11
|
+
extend self
|
12
|
+
include ActiveSupport::Configurable
|
13
|
+
|
14
|
+
config_accessor :server_rendering_file do
|
15
|
+
"server_rendering.js"
|
16
|
+
end
|
17
|
+
|
18
|
+
config_accessor :server_rendering_source_map do
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
config_accessor :logger do
|
23
|
+
Logger.new(STDOUT)
|
24
|
+
end
|
25
|
+
|
26
|
+
config_accessor :context_options do
|
27
|
+
{
|
28
|
+
timeout: 1000,
|
29
|
+
ensure_gc_after_idle: 2000
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_functions
|
34
|
+
<<~JS
|
35
|
+
delete this.setTimeout;
|
36
|
+
delete this.setInterval;
|
37
|
+
delete this.clearTimeout;
|
38
|
+
delete this.clearInterval;
|
39
|
+
delete this.setImmediate;
|
40
|
+
delete this.clearImmediate;
|
41
|
+
JS
|
42
|
+
end
|
43
|
+
|
44
|
+
def logger
|
45
|
+
config.logger
|
46
|
+
end
|
47
|
+
|
48
|
+
def renderer
|
49
|
+
<<~JS
|
50
|
+
var __renderer;
|
51
|
+
function setHumidRenderer(fn) {
|
52
|
+
__renderer = fn;
|
53
|
+
}
|
54
|
+
JS
|
55
|
+
end
|
56
|
+
|
57
|
+
def context
|
58
|
+
if @@context && Webpacker.env.development? && Webpacker.compiler.stale?
|
59
|
+
Webpacker.compiler.compile
|
60
|
+
dispose
|
61
|
+
create_context
|
62
|
+
else
|
63
|
+
@@context
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def dispose
|
68
|
+
if @@context
|
69
|
+
@@context.dispose
|
70
|
+
@@context = nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_context
|
75
|
+
ctx = MiniRacer::Context.new(config.context_options)
|
76
|
+
ctx.attach("console.log", proc { |err| logger.debug(err.to_s) })
|
77
|
+
ctx.attach("console.info", proc { |err| logger.info(err.to_s) })
|
78
|
+
ctx.attach("console.error", proc { |err| logger.error(err.to_s) })
|
79
|
+
ctx.attach("console.warn", proc { |err| logger.warn(err.to_s) })
|
80
|
+
|
81
|
+
js = ""
|
82
|
+
js << remove_functions
|
83
|
+
js << renderer
|
84
|
+
ctx.eval(js)
|
85
|
+
|
86
|
+
public_path = Webpacker.config.public_path
|
87
|
+
asset_path = public_path.join(Webpacker.manifest.lookup(config.server_rendering_file)[1..-1])
|
88
|
+
filename = File.basename(asset_path.to_s)
|
89
|
+
ctx.eval(File.read(asset_path), filename: filename)
|
90
|
+
|
91
|
+
if config.server_rendering_source_map
|
92
|
+
map_path = public_path.join(Webpacker.manifest.lookup(config.server_rendering_source_map)[1..-1])
|
93
|
+
ctx.attach("readSourceMap", proc { File.read(map_path) })
|
94
|
+
end
|
95
|
+
|
96
|
+
@@context = ctx
|
97
|
+
end
|
98
|
+
|
99
|
+
def render(*args)
|
100
|
+
ActiveSupport::Notifications.instrument("render.humid") do
|
101
|
+
@@context.call("__renderer", *args)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
Humid::LogSubscriber.attach_to :humid
|
107
|
+
ActiveSupport.on_load(:action_controller) do
|
108
|
+
include Humid::ControllerRuntime
|
109
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Humid
|
2
|
+
module ControllerRuntime
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def log_process_action(payload)
|
7
|
+
messages, humid_runtime = super, payload[:humid_runtime]
|
8
|
+
messages << ("Humid SSR: %.1fms" % humid_runtime.to_f) if humid_runtime
|
9
|
+
messages
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_internal :humid_runtime
|
16
|
+
|
17
|
+
# Reset the runtime before each action.
|
18
|
+
def process_action(action, *args)
|
19
|
+
Humid::LogSubscriber.reset_runtime
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def cleanup_view_runtime
|
24
|
+
if logger&.info?
|
25
|
+
humid_rt_before_render = Humid::LogSubscriber.reset_runtime
|
26
|
+
self.humid_runtime = (humid_runtime || 0) + humid_rt_before_render
|
27
|
+
runtime = super
|
28
|
+
humid_rt_after_render = Humid::LogSubscriber.reset_runtime
|
29
|
+
self.humid_runtime += humid_rt_after_render
|
30
|
+
runtime - humid_rt_after_render
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def append_info_to_payload(payload)
|
37
|
+
super
|
38
|
+
payload[:humid_runtime] = (humid_runtime || 0) + Humid::LogSubscriber.reset_runtime
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Humid
|
2
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
|
+
thread_cattr_accessor :humid_runtime
|
4
|
+
|
5
|
+
def self.runtime=(value)
|
6
|
+
self.humid_runtime = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.runtime
|
10
|
+
self.humid_runtime ||= 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.reset_runtime
|
14
|
+
rt, self.runtime = runtime, 0
|
15
|
+
rt
|
16
|
+
end
|
17
|
+
|
18
|
+
def render(event)
|
19
|
+
self.class.runtime += event.duration
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative "./support/helper"
|
2
|
+
|
3
|
+
describe Humid::ControllerRuntime do
|
4
|
+
controller_runtime = Humid::ControllerRuntime
|
5
|
+
|
6
|
+
def set_metric value
|
7
|
+
Humid::LogSubscriber.runtime = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def clear_metric!
|
11
|
+
Humid::LogSubscriber.reset_runtime = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
reference_controller_class = Class.new {
|
15
|
+
def process_action *_
|
16
|
+
@process_action = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def cleanup_view_runtime *_
|
20
|
+
@cleanup_view_runtime.call
|
21
|
+
end
|
22
|
+
|
23
|
+
def append_info_to_payload *_
|
24
|
+
@append_info_to_payload = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.log_process_action *_
|
28
|
+
@log_process_action.call
|
29
|
+
end
|
30
|
+
}
|
31
|
+
|
32
|
+
controller_class = Class.new reference_controller_class do
|
33
|
+
include controller_runtime
|
34
|
+
|
35
|
+
def logger
|
36
|
+
Logger.new(STDOUT)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:controller) { controller_class.new }
|
41
|
+
|
42
|
+
it "resets the metric before each action" do
|
43
|
+
set_metric 42
|
44
|
+
controller.send(:process_action, "foo")
|
45
|
+
expect(Humid::LogSubscriber.runtime).to be(0)
|
46
|
+
expect(controller.instance_variable_get("@process_action")).to be(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "strips the metric of other sources of the runtime" do
|
50
|
+
set_metric 1
|
51
|
+
controller.instance_variable_set "@cleanup_view_runtime", -> {
|
52
|
+
controller.instance_variable_set "@cleanup_view_runtime", true
|
53
|
+
set_metric 13
|
54
|
+
42
|
55
|
+
}
|
56
|
+
returned = controller.send :cleanup_view_runtime
|
57
|
+
expect(controller.instance_variable_get("@cleanup_view_runtime")).to be(true)
|
58
|
+
expect(controller.humid_runtime).to eq(14)
|
59
|
+
expect(returned).to be(29)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "appends the metric to payload" do
|
63
|
+
payload = {}
|
64
|
+
set_metric 42
|
65
|
+
controller.send :append_info_to_payload, payload
|
66
|
+
expect(controller.instance_variable_get("@append_info_to_payload")).to be(true)
|
67
|
+
expect(payload[:humid_runtime]).to eq(42)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "adds metric to log message" do
|
71
|
+
controller_class.instance_variable_set "@log_process_action", -> {
|
72
|
+
controller_class.instance_variable_set "@log_process_action", true
|
73
|
+
[]
|
74
|
+
}
|
75
|
+
messages = controller_class.log_process_action humid_runtime: 42.101
|
76
|
+
expect(controller_class.instance_variable_get("@log_process_action")).to be(true)
|
77
|
+
expect(messages).to eq(["Humid SSR: 42.1ms"])
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative "./support/helper"
|
2
|
+
require "active_support/log_subscriber/test_helper"
|
3
|
+
require "byebug"
|
4
|
+
|
5
|
+
RSpec.describe Humid::LogSubscriber do
|
6
|
+
around(:each) do |example|
|
7
|
+
app_path = File.expand_path("./testapp", File.dirname(__FILE__))
|
8
|
+
Dir.chdir(app_path) do
|
9
|
+
example.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
Humid::LogSubscriber.reset_runtime
|
15
|
+
end
|
16
|
+
|
17
|
+
context ".runtime" do
|
18
|
+
it "is returns the runtime from the thread local" do
|
19
|
+
expect(Humid::LogSubscriber.runtime).to eql 0
|
20
|
+
key = "attr_Humid::LogSubscriber_humid_runtime"
|
21
|
+
Thread.current[key] = 3
|
22
|
+
expect(Humid::LogSubscriber.runtime).to eql 3
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context ".runtime=" do
|
27
|
+
it "sets the runtime in a thread-safe manner" do
|
28
|
+
expect(Humid::LogSubscriber.runtime).to eql 0
|
29
|
+
Humid::LogSubscriber.runtime = 3
|
30
|
+
key = "attr_Humid::LogSubscriber_humid_runtime"
|
31
|
+
expect(Thread.current[key]).to eql 3
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context ".reset_runtime" do
|
36
|
+
it "resets the runtime" do
|
37
|
+
Humid::LogSubscriber.runtime = 3
|
38
|
+
key = "attr_Humid::LogSubscriber_humid_runtime"
|
39
|
+
expect(Thread.current[key]).to eql 3
|
40
|
+
|
41
|
+
Humid::LogSubscriber.reset_runtime
|
42
|
+
expect(Thread.current[key]).to eql 0
|
43
|
+
expect(Humid::LogSubscriber.runtime).to eql 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "is attached" do
|
48
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
49
|
+
Humid.create_context
|
50
|
+
expect(Humid::LogSubscriber.runtime).to eql(0)
|
51
|
+
Humid.render
|
52
|
+
expect(Humid::LogSubscriber.runtime).to be > 0
|
53
|
+
end
|
54
|
+
end
|
data/spec/render_spec.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require_relative "./support/helper"
|
2
|
+
|
3
|
+
RSpec.describe "Humid" do
|
4
|
+
around(:each) do |example|
|
5
|
+
app_path = File.expand_path("./testapp", File.dirname(__FILE__))
|
6
|
+
Dir.chdir(app_path) do
|
7
|
+
example.run
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "create_context" do
|
12
|
+
after(:each) do
|
13
|
+
Humid.dispose
|
14
|
+
end
|
15
|
+
|
16
|
+
it "creates a context with initial js" do
|
17
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
18
|
+
Humid.create_context
|
19
|
+
|
20
|
+
expect(Humid.context).to be_kind_of(MiniRacer::Context)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "does not have timeouts, immediates, and intervals" do
|
24
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
25
|
+
|
26
|
+
Humid.create_context
|
27
|
+
|
28
|
+
expect {
|
29
|
+
Humid.context.eval("setTimeout()")
|
30
|
+
}.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setTimeout is not defined")
|
31
|
+
expect {
|
32
|
+
Humid.context.eval("setInterval()")
|
33
|
+
}.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setInterval is not defined")
|
34
|
+
expect {
|
35
|
+
Humid.context.eval("clearTimeout()")
|
36
|
+
}.to raise_error(MiniRacer::RuntimeError, "ReferenceError: clearTimeout is not defined")
|
37
|
+
expect {
|
38
|
+
Humid.context.eval("setImmediate()")
|
39
|
+
}.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setImmediate is not defined")
|
40
|
+
expect {
|
41
|
+
Humid.context.eval("clearImmediate()")
|
42
|
+
}.to raise_error(MiniRacer::RuntimeError, "ReferenceError: clearImmediate is not defined")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "proxies to Rails logger" do
|
46
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
47
|
+
Humid.create_context
|
48
|
+
expect(Humid.logger).to receive(:info).with("hello")
|
49
|
+
|
50
|
+
Humid.context.eval("console.info('hello')")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "context" do
|
55
|
+
it "returns the created context" do
|
56
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
57
|
+
|
58
|
+
Humid.create_context
|
59
|
+
|
60
|
+
expect(Humid.context).to be_kind_of(MiniRacer::Context)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the js is stale and env is NOT dev`" do
|
64
|
+
it "does not recompile the JS" do
|
65
|
+
allow(Webpacker).to receive_message_chain("env.development?") { false }
|
66
|
+
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
67
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
68
|
+
|
69
|
+
Humid.create_context
|
70
|
+
prev_context = Humid.context
|
71
|
+
expect(prev_context).to be_kind_of(MiniRacer::Context)
|
72
|
+
|
73
|
+
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
74
|
+
|
75
|
+
next_context = Humid.context
|
76
|
+
|
77
|
+
expect(prev_context).to eql(next_context)
|
78
|
+
expect(next_context).to be_kind_of(MiniRacer::Context)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when the js is stale and env is development" do
|
83
|
+
it "compiles the JS" do
|
84
|
+
allow(Webpacker).to receive_message_chain("env.development?") { true }
|
85
|
+
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
86
|
+
allow(Webpacker).to receive_message_chain("compiler.compile")
|
87
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
88
|
+
|
89
|
+
Humid.create_context
|
90
|
+
prev_context = Humid.context
|
91
|
+
expect(prev_context).to be_kind_of(MiniRacer::Context)
|
92
|
+
|
93
|
+
allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
|
94
|
+
|
95
|
+
next_context = Humid.context
|
96
|
+
|
97
|
+
expect(prev_context).to_not eql(next_context)
|
98
|
+
expect(next_context).to be_kind_of(MiniRacer::Context)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "render" do
|
104
|
+
it "returns a js output" do
|
105
|
+
allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
|
106
|
+
Humid.create_context
|
107
|
+
|
108
|
+
expect(Humid.render).to eql("hello")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "applys args to the func" do
|
112
|
+
allow(Humid.config).to receive("server_rendering_file") { "args.js" }
|
113
|
+
Humid.create_context
|
114
|
+
|
115
|
+
args = ["a", 1, 2, [], {}]
|
116
|
+
|
117
|
+
expect(Humid.render(*args)).to eql({"0" => "a", "1" => 1, "2" => 2, "3" => [], "4" => {}})
|
118
|
+
end
|
119
|
+
|
120
|
+
it "can use source maps to see errors" do
|
121
|
+
allow(Humid.config).to receive("server_rendering_file") { "reporting.js" }
|
122
|
+
allow(Humid.config).to receive("server_rendering_source_map") {
|
123
|
+
"reporting.js.map"
|
124
|
+
}
|
125
|
+
|
126
|
+
Humid.create_context
|
127
|
+
|
128
|
+
expect {
|
129
|
+
Humid.render
|
130
|
+
}.to raise_error { |error|
|
131
|
+
expect(error).to be_a(MiniRacer::RuntimeError)
|
132
|
+
expect(error.message).to eql("Error: ^^ Look! These stack traces map to the actual source code :)")
|
133
|
+
expect(error.backtrace[0]).to eql("JavaScript at throwSomeError (/webpack:/app/javascript/packs/components/error-causing-component.js:2:1)")
|
134
|
+
expect(error.backtrace[1]).to eql("JavaScript at ErrorCausingComponent (/webpack:/app/javascript/packs/components/error-causing-component.js:8:1)")
|
135
|
+
expect(error.backtrace[2]).to eql("JavaScript at /webpack:/app/javascript/packs/reporting.js:18:1")
|
136
|
+
}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: humid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Johny Ho
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: webpacker
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mini_racer
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '6.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '6.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '12.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '12.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '9.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '9.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '6.1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '6.1'
|
111
|
+
description: Javascript SSR rendering for Rails
|
112
|
+
email: jho406@gmail.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- README.md
|
118
|
+
- lib/humid.rb
|
119
|
+
- lib/humid/controller_runtime.rb
|
120
|
+
- lib/humid/log_subscriber.rb
|
121
|
+
- lib/humid/version.rb
|
122
|
+
- spec/controller_runtime_spec.rb
|
123
|
+
- spec/log_subscriber_spec.rb
|
124
|
+
- spec/render_spec.rb
|
125
|
+
homepage: https://github.com/thoughtbot/humid/
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubygems_version: 3.1.2
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Javascript SSR rendering for Rails
|
148
|
+
test_files:
|
149
|
+
- spec/render_spec.rb
|
150
|
+
- spec/log_subscriber_spec.rb
|
151
|
+
- spec/controller_runtime_spec.rb
|