isomorfeus-preact 10.6.33 → 10.6.37
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/isomorfeus/preact/config.rb +1 -1
- data/lib/isomorfeus/preact_view_helper.rb +92 -100
- data/lib/isomorfeus/ssr.rb +75 -0
- data/lib/isomorfeus/top_level.rb +2 -24
- data/lib/isomorfeus/top_level_ssr.rb +23 -0
- data/lib/isomorfeus-preact.rb +1 -0
- data/lib/isomorfeus_preact/lucid_component/api.rb +0 -1
- data/lib/isomorfeus_preact/lucid_component/initializer.rb +0 -1
- data/lib/isomorfeus_preact/lucid_func/initializer.rb +0 -1
- data/lib/lucid_app/context.rb +1 -1
- data/lib/nano_css.rb +10 -10
- data/lib/preact/version.rb +1 -1
- data/lib/preact.rb +4 -3
- data/node_modules/.package-lock.json +3 -3
- data/node_modules/preact/compat/LICENSE +21 -0
- data/node_modules/preact/compat/jsx-dev-runtime.js +2 -0
- data/node_modules/preact/compat/jsx-dev-runtime.mjs +2 -0
- data/node_modules/preact/compat/jsx-runtime.js +2 -0
- data/node_modules/preact/compat/jsx-runtime.mjs +2 -0
- data/node_modules/preact/debug/LICENSE +21 -0
- data/node_modules/preact/devtools/LICENSE +21 -0
- data/node_modules/preact/devtools/dist/devtools.js +1 -1
- data/node_modules/preact/devtools/dist/devtools.js.map +1 -1
- data/node_modules/preact/devtools/dist/devtools.mjs +1 -1
- data/node_modules/preact/devtools/dist/devtools.module.js +1 -1
- data/node_modules/preact/devtools/dist/devtools.module.js.map +1 -1
- data/node_modules/preact/devtools/dist/devtools.umd.js +1 -1
- data/node_modules/preact/devtools/dist/devtools.umd.js.map +1 -1
- data/node_modules/preact/devtools/src/devtools.js +1 -1
- data/node_modules/preact/dist/preact.js +1 -1
- data/node_modules/preact/dist/preact.js.map +1 -1
- data/node_modules/preact/dist/preact.min.js +1 -1
- data/node_modules/preact/dist/preact.min.js.map +1 -1
- data/node_modules/preact/dist/preact.mjs +1 -1
- data/node_modules/preact/dist/preact.module.js +1 -1
- data/node_modules/preact/dist/preact.module.js.map +1 -1
- data/node_modules/preact/dist/preact.umd.js +1 -1
- data/node_modules/preact/dist/preact.umd.js.map +1 -1
- data/node_modules/preact/hooks/LICENSE +21 -0
- data/node_modules/preact/jsx-runtime/LICENSE +21 -0
- data/node_modules/preact/package.json +1 -1
- data/node_modules/preact/src/diff/index.js +6 -3
- data/package.json +1 -1
- metadata +15 -9
- data/lib/isomorfeus_preact/lucid_component/instance_store_proxy.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f82bf99a53bc67d3fd34a366579d35c1e560c6dd860e9981dca3c24e58a4bed6
|
4
|
+
data.tar.gz: c031adbcb8102d1225012d1526e602b70275b872be1b74c96828c1e53c20c78d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c238454b703626f7db793109fe26c81443e55ffe6bae3e0a717132369bcdb8854c5319bc56db2780f976b4721e1e0f26bd07ddb21cddcb04fe0d8a15bc63e4cf
|
7
|
+
data.tar.gz: 28b3a937f2e305534e7cfc038de0f76445128b58c464d6596b5de36e79d3f25f709956d34969f8e681d3780c0d2fe9e4a07d672005aba5cc205c9ab477493e15
|
@@ -4,9 +4,9 @@ module Isomorfeus
|
|
4
4
|
base.include Isomorfeus::AssetManager::ViewHelper
|
5
5
|
end
|
6
6
|
|
7
|
-
def cached_mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4)
|
7
|
+
def cached_mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4, force: false)
|
8
8
|
key = "#{component_name}#{props}#{asset}"
|
9
|
-
if Isomorfeus.production?
|
9
|
+
if Isomorfeus.production? && !force
|
10
10
|
render_result, @ssr_response_status, @ssr_styles = component_cache.fetch(key)
|
11
11
|
return render_result if render_result
|
12
12
|
end
|
@@ -17,19 +17,13 @@ module Isomorfeus
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4)
|
20
|
+
ssr_start_time = Time.now if Isomorfeus.development?
|
20
21
|
@ssr_response_status = nil
|
21
22
|
@ssr_styles = nil
|
22
|
-
thread_id_asset = "#{Thread.current.object_id}#{asset_key}"
|
23
23
|
render_result = "<div data-iso-env=\"#{Isomorfeus.env}\" data-iso-root=\"#{component_name}\" data-iso-props='#{Oj.dump(props, mode: :strict)}'"
|
24
24
|
if !skip_ssr && (Isomorfeus.server_side_rendering || use_ssr)
|
25
|
+
thread_id_asset = "#{Thread.current.object_id}#{asset_key}"
|
25
26
|
if Isomorfeus.development?
|
26
|
-
# always create a new context, effectively reloading code
|
27
|
-
# delete the existing context first, saves memory
|
28
|
-
if Isomorfeus.ssr_contexts.key?(thread_id_asset)
|
29
|
-
uuid = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@uuid)
|
30
|
-
runtime = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@runtime)
|
31
|
-
runtime.vm.delete_context(uuid)
|
32
|
-
end
|
33
27
|
begin
|
34
28
|
init_speednode_context(asset_key, thread_id_asset)
|
35
29
|
rescue Exception => e
|
@@ -41,7 +35,7 @@ module Isomorfeus
|
|
41
35
|
end
|
42
36
|
end
|
43
37
|
|
44
|
-
|
38
|
+
ctx = Isomorfeus.ssr_contexts[thread_id_asset]
|
45
39
|
pass = 0
|
46
40
|
# if location_host and scheme are given and if Transport is loaded, connect and then render,
|
47
41
|
# otherwise do not render because only one pass is required
|
@@ -53,110 +47,84 @@ module Isomorfeus
|
|
53
47
|
# build javascript for rendering first pass
|
54
48
|
# it will initialize buffers to guard against leaks, maybe caused by previous exceptions
|
55
49
|
javascript = <<~JAVASCRIPT
|
56
|
-
|
57
|
-
global.Opal.Preact.active_components = [];
|
58
|
-
global.Opal.Preact.active_redux_components = [];
|
59
|
-
global.FirstPassFinished = false;
|
60
|
-
global.Exception = false;
|
61
|
-
global.IsomorfeusSessionId = '#{Thread.current[:isomorfeus_session_id]}';
|
62
|
-
global.Opal.Isomorfeus['$env=']('#{Isomorfeus.env}');
|
63
|
-
if (typeof global.Opal.Isomorfeus["$current_locale="] === 'function') {
|
64
|
-
global.Opal.Isomorfeus["$current_locale="]('#{props[:locale]}');
|
65
|
-
} else if (typeof global.Opal.Isomorfeus["$negotiated_locale="] === 'function') { // remove later on
|
66
|
-
global.Opal.Isomorfeus["$negotiated_locale="]('#{props[:locale]}');
|
67
|
-
}
|
68
|
-
global.Opal.Isomorfeus['$force_init!']();
|
69
|
-
global.Opal.Isomorfeus['$ssr_response_status='](200);
|
70
|
-
global.Opal.Isomorfeus.TopLevel['$ssr_route_path=']('#{props[:location]}');
|
71
|
-
let api_ws_path = '#{api_ws_path}';
|
72
|
-
let exception;
|
73
|
-
if (typeof global.Opal.Isomorfeus.Transport !== 'undefined' && api_ws_path !== '') {
|
74
|
-
global.Opal.Isomorfeus.TopLevel["$transport_ws_url="]("#{transport_ws_url}");
|
75
|
-
global.Opal.send(global.Opal.Isomorfeus.Transport.$promise_connect(global.IsomorfeusSessionId), 'then', [], ($$1 = function(){
|
76
|
-
try {
|
77
|
-
global.Opal.Isomorfeus.TopLevel.$render_component_to_string('#{component_name}', #{Oj.dump(props, mode: :strict)});
|
78
|
-
global.FirstPassFinished = 'transport';
|
79
|
-
} catch (e) {
|
80
|
-
global.Exception = e;
|
81
|
-
global.FirstPassFinished = 'transport';
|
82
|
-
}
|
83
|
-
}, $$1.$$s = this, $$1.$$arity = 0, $$1))
|
84
|
-
return false;
|
85
|
-
} else { global.FirstPassFinished = true; return true; };
|
50
|
+
return Opal.Isomorfeus.SSR.first_pass('#{Thread.current[:isomorfeus_session_id]}', '#{Isomorfeus.env}', '#{props[:locale]}', '#{props[:location]}', '#{api_ws_path}', '#{transport_ws_url}', '#{component_name}', #{Oj.dump(props, mode: :strict)})
|
86
51
|
JAVASCRIPT
|
52
|
+
|
53
|
+
finished = false
|
87
54
|
# execute first render pass
|
88
55
|
begin
|
89
56
|
pass += 1
|
90
|
-
|
57
|
+
has_transport, has_store, need_further_pass, exception = ctx.exec(javascript)
|
58
|
+
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
|
91
59
|
rescue Exception => e
|
92
60
|
Isomorfeus.raise_error(error: e)
|
93
61
|
end
|
94
|
-
|
95
|
-
|
96
|
-
|
62
|
+
|
63
|
+
if has_transport
|
64
|
+
# wait for first pass to finish
|
65
|
+
first_pass_finished, need_further_pass, exception = ctx.eval_script(key: :first_pass_check)
|
97
66
|
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
|
98
67
|
unless first_pass_finished
|
99
68
|
start_time = Time.now
|
100
69
|
while !first_pass_finished
|
101
70
|
break if (Time.now - start_time) > 10
|
102
|
-
sleep 0.
|
103
|
-
first_pass_finished =
|
71
|
+
sleep 0.005
|
72
|
+
first_pass_finished, need_further_pass, exception = ctx.eval_script(key: :first_pass_check)
|
73
|
+
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
|
104
74
|
end
|
105
75
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
76
|
+
|
77
|
+
# wait for transport to settle
|
78
|
+
transport_busy = ctx.eval_script(key: :transport_busy)
|
79
|
+
if transport_busy
|
80
|
+
start_time = Time.now
|
81
|
+
while transport_busy
|
82
|
+
break if (Time.now - start_time) > 5
|
83
|
+
sleep 0.005
|
84
|
+
transport_busy = ctx.eval_script(key: :transport_busy)
|
116
85
|
end
|
117
86
|
end
|
118
87
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
88
|
+
|
89
|
+
if !need_further_pass
|
90
|
+
rendered_tree, application_state, @ssr_styles, @ssr_response_status, exception = ctx.eval_script(key: :first_pass_result)
|
91
|
+
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
|
92
|
+
else
|
93
|
+
start_time = Time.now
|
94
|
+
script_key = if has_transport && has_store
|
95
|
+
:sill_busy
|
96
|
+
elsif has_transport
|
97
|
+
:transport_busy
|
98
|
+
elsif has_store
|
99
|
+
:store_busy
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
while need_further_pass
|
104
|
+
# execute further render passes
|
105
|
+
javascript = <<~JAVASCRIPT
|
106
|
+
return Opal.Isomorfeus.SSR.further_pass('#{component_name}', #{Oj.dump(props, mode: :strict)})
|
107
|
+
JAVASCRIPT
|
108
|
+
pass += 1
|
109
|
+
rendered_tree, application_state, @ssr_styles, @ssr_response_status, need_further_pass, exception = ctx.exec(javascript)
|
110
|
+
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
|
111
|
+
if need_further_pass && script_key
|
112
|
+
break if (Time.now - start_time) > 5
|
113
|
+
need_further_pass = ctx.eval_script(key: script_key)
|
114
|
+
while need_further_pass
|
115
|
+
break if (Time.now - start_time) > 4
|
116
|
+
sleep 0.01
|
117
|
+
need_further_pass = ctx.eval_script(key: script_key)
|
118
|
+
end
|
119
|
+
break if pass >= max_passes
|
120
|
+
else
|
121
|
+
break
|
122
|
+
end
|
150
123
|
end
|
151
|
-
pass += 1
|
152
|
-
rendered_tree, application_state, @ssr_styles, @ssr_response_status, transport_busy, exception = Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
|
153
|
-
break if pass >= max_passes
|
154
124
|
end
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
|
159
|
-
Isomorfeus.raise_error(message: exception['message'], stack: exception['stack']) if exception
|
125
|
+
|
126
|
+
ctx.eval_script(key: :transport_disconnect) if has_transport
|
127
|
+
|
160
128
|
render_result << " data-iso-hydrated='true'" if rendered_tree
|
161
129
|
if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
|
162
130
|
render_result << " data-iso-usid=#{Oj.dump(Isomorfeus.current_user.sid, mode: :strict)}"
|
@@ -170,10 +138,10 @@ module Isomorfeus
|
|
170
138
|
render_result << " data-iso-nloc='#{props[:locale]}'>"
|
171
139
|
end
|
172
140
|
render_result << '</div>'
|
173
|
-
if Isomorfeus.server_side_rendering
|
141
|
+
if Isomorfeus.server_side_rendering && !skip_ssr
|
174
142
|
render_result = "<script type='application/javascript'>\nServerSideRenderingStateJSON = #{Oj.dump(application_state, mode: :strict)}\n</script>\n" << render_result
|
143
|
+
puts "PreactViewHelper Server Side Rendering rendered #{pass} passes and took ~#{((Time.now - ssr_start_time)*1000).to_i}ms" if Isomorfeus.development?
|
175
144
|
end
|
176
|
-
STDERR.puts "PreactViewHelper Server Side Rendering rendered #{pass} passes and took ~#{((Time.now - start_time)*1000).to_i}ms" if Isomorfeus.development? && !skip_ssr
|
177
145
|
render_result
|
178
146
|
end
|
179
147
|
|
@@ -198,8 +166,32 @@ module Isomorfeus
|
|
198
166
|
def init_speednode_context(asset_key, thread_id_asset)
|
199
167
|
asset = Isomorfeus.assets[asset_key]
|
200
168
|
raise "#{self.class.name}: Asset not found: #{asset_key}" unless asset
|
201
|
-
|
202
|
-
|
169
|
+
if !Isomorfeus.ssr_contexts.key?(thread_id_asset) || !asset.bundled?
|
170
|
+
if Isomorfeus.ssr_contexts.key?(thread_id_asset)
|
171
|
+
uuid = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@uuid)
|
172
|
+
runtime = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@runtime)
|
173
|
+
runtime.vm.delete_context(uuid)
|
174
|
+
end
|
175
|
+
asset_manager.transition(asset_key, asset)
|
176
|
+
Isomorfeus.ssr_contexts[thread_id_asset] = ExecJS.permissive_compile(asset.bundle)
|
177
|
+
ctx = Isomorfeus.ssr_contexts[thread_id_asset]
|
178
|
+
ctx.exec(top_level_mod)
|
179
|
+
ctx.exec(ssr_mod)
|
180
|
+
ctx.add_script(key: :first_pass_check, source: '[global.FirstPassFinished, global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false ]')
|
181
|
+
ctx.add_script(key: :first_pass_result, source: 'Opal.Isomorfeus.SSR.first_pass_result()')
|
182
|
+
ctx.add_script(key: :still_busy, source: 'let nfp = global.Opal.Isomorfeus.Transport["$busy?"]() || global.Opal.Isomorfeus.store["$recently_dispatched?"](); (nfp == nil) ? false : nfp;')
|
183
|
+
ctx.add_script(key: :store_busy, source: 'let nfp = global.Opal.Isomorfeus.store["$recently_dispatched?"](); (nfp == nil) ? false : nfp;')
|
184
|
+
ctx.add_script(key: :transport_busy, source: 'global.Opal.Isomorfeus.Transport["$busy?"]()')
|
185
|
+
ctx.add_script(key: :transport_disconnect, source: 'global.Opal.Isomorfeus.Transport.$disconnect()')
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def ssr_mod
|
190
|
+
@_ssr_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'ssr.rb'))))
|
191
|
+
end
|
192
|
+
|
193
|
+
def top_level_mod
|
194
|
+
@_top_level_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'top_level_ssr.rb'))))
|
203
195
|
end
|
204
196
|
end
|
205
197
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Isomorfeus
|
2
|
+
module SSR
|
3
|
+
%x{
|
4
|
+
self.first_pass = function(session_id, env, locale, location, api_ws_path, transport_ws_url, component_name, props) {
|
5
|
+
global.Opal.Preact.render_buffer = [];
|
6
|
+
global.Opal.Preact.active_components = [];
|
7
|
+
global.Opal.Preact.active_redux_components = [];
|
8
|
+
global.FirstPassFinished = false;
|
9
|
+
global.NeedFurtherPass = false;
|
10
|
+
global.RenderedTree = '';
|
11
|
+
global.Exception = false;
|
12
|
+
global.IsomorfeusSessionId = session_id;
|
13
|
+
global.HasTransport = (typeof global.Opal.Isomorfeus.Transport !== 'undefined') && (api_ws_path !== '');
|
14
|
+
global.HasStore = typeof global.Opal.Isomorfeus.store !== 'undefined';
|
15
|
+
global.Opal.Isomorfeus['$env='](env);
|
16
|
+
if (typeof global.Opal.Isomorfeus["$current_locale="] === 'function') { global.Opal.Isomorfeus["$current_locale="](''); }
|
17
|
+
global.Opal.Isomorfeus['$force_init!']();
|
18
|
+
global.Opal.Isomorfeus['$ssr_response_status='](200);
|
19
|
+
global.Opal.Isomorfeus.TopLevel['$ssr_route_path='](location);
|
20
|
+
if (global.HasTransport) {
|
21
|
+
global.Opal.Isomorfeus.TopLevel["$transport_ws_url="](transport_ws_url);
|
22
|
+
global.Opal.send(global.Opal.Isomorfeus.Transport.$promise_connect(global.IsomorfeusSessionId), 'then', [], ($$1 = function(){
|
23
|
+
try {
|
24
|
+
global.RenderedTree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
|
25
|
+
let nfp = global.Opal.Isomorfeus.Transport["$busy?"]() || global.Opal.Isomorfeus.store['$recently_dispatched?']();
|
26
|
+
global.NeedFurtherPass = (nfp == nil) ? false : nfp;
|
27
|
+
global.FirstPassFinished = false;
|
28
|
+
} catch (e) {
|
29
|
+
global.Exception = e;
|
30
|
+
global.NeedFurtherPass = false;
|
31
|
+
}
|
32
|
+
}, $$1.$$s = this, $$1.$$arity = 0, $$1))
|
33
|
+
} else {
|
34
|
+
try {
|
35
|
+
global.RenderedTree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
|
36
|
+
if (global.HasStore) {
|
37
|
+
let nfp = global.Opal.Isomorfeus.store['$recently_dispatched?']();
|
38
|
+
global.NeedFurtherPass = (nfp == nil) ? false : nfp;
|
39
|
+
}
|
40
|
+
} catch (e) {
|
41
|
+
global.Exception = e;
|
42
|
+
global.NeedFurtherPass = false;
|
43
|
+
}
|
44
|
+
};
|
45
|
+
return [global.HasTransport, global.HasStore, global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
|
46
|
+
}
|
47
|
+
|
48
|
+
self.first_pass_result = function() {
|
49
|
+
let ssr_styles;
|
50
|
+
let application_state = global.Opal.Isomorfeus.store.native.getState();
|
51
|
+
if (typeof global.NanoCSSInstance !== 'undefined') { ssr_styles = global.NanoCSSInstance.raw }
|
52
|
+
return [global.RenderedTree, application_state, ssr_styles, global.Opal.Isomorfeus['$ssr_response_status'](), global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
|
53
|
+
}
|
54
|
+
|
55
|
+
self.further_pass = function(component_name, props) {
|
56
|
+
global.Opal.Preact.render_buffer = [];
|
57
|
+
global.Opal.Preact.active_components = [];
|
58
|
+
global.Opal.Preact.active_redux_components = [];
|
59
|
+
global.Exception = false;
|
60
|
+
let rendered_tree;
|
61
|
+
let ssr_styles;
|
62
|
+
try {
|
63
|
+
rendered_tree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
|
64
|
+
} catch (e) {
|
65
|
+
global.Exception = e;
|
66
|
+
}
|
67
|
+
let application_state = global.Opal.Isomorfeus.store.native.getState();
|
68
|
+
if (typeof global.NanoCSSInstance !== 'undefined') { ssr_styles = global.NanoCSSInstance.raw }
|
69
|
+
let nfp = (global.HasTransport && global.Opal.Isomorfeus.Transport["$busy?"]()) || (global.HasStore && global.Opal.Isomorfeus.store["$recently_dispatched?"]());
|
70
|
+
global.NeedFurtherPass = (nfp == nil) ? false : nfp;
|
71
|
+
return [rendered_tree, application_state, ssr_styles, global.Opal.Isomorfeus['$ssr_response_status'](), global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
data/lib/isomorfeus/top_level.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Isomorfeus
|
2
2
|
class TopLevel
|
3
3
|
class << self
|
4
|
-
if on_browser?
|
4
|
+
if on_browser?
|
5
5
|
def mount!
|
6
6
|
Isomorfeus.init
|
7
7
|
Isomorfeus::TopLevel.on_ready do
|
@@ -94,29 +94,7 @@ module Isomorfeus
|
|
94
94
|
hydrated ? Preact.hydrate(top, element) : Preact.render(top, element)
|
95
95
|
Isomorfeus.top_component = top
|
96
96
|
end
|
97
|
-
|
98
|
-
attr_accessor :ssr_route_path
|
99
|
-
attr_accessor :transport_ws_url
|
100
|
-
|
101
|
-
def mount!
|
102
|
-
# nothing, but keep it for compatibility with browser
|
103
|
-
end
|
104
|
-
|
105
|
-
def render_component_to_string(component_name, props)
|
106
|
-
component = nil
|
107
|
-
%x{
|
108
|
-
if (typeof component_name === 'string' || component_name instanceof String) {
|
109
|
-
component = component_name.split(".").reduce(function(o, x) {
|
110
|
-
return (o !== null && typeof o[x] !== "undefined" && o[x] !== null) ? o[x] : null;
|
111
|
-
}, Opal.global)
|
112
|
-
} else {
|
113
|
-
component = component_name;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
component = Isomorfeus.cached_component_class(component_name) unless component
|
117
|
-
Preact.render_to_string(Preact.create_element(component, `Opal.Hash.$new(props)`))
|
118
|
-
end
|
119
|
-
end # execution environment
|
97
|
+
end
|
120
98
|
end
|
121
99
|
end
|
122
100
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Isomorfeus
|
2
|
+
class TopLevel
|
3
|
+
class << self
|
4
|
+
attr_accessor :ssr_route_path
|
5
|
+
attr_accessor :transport_ws_url
|
6
|
+
|
7
|
+
def render_component_to_string(component_name, props)
|
8
|
+
component = nil
|
9
|
+
%x{
|
10
|
+
if (typeof component_name === 'string' || component_name instanceof String) {
|
11
|
+
component = component_name.split(".").reduce(function(o, x) {
|
12
|
+
return (o !== null && typeof o[x] !== "undefined" && o[x] !== null) ? o[x] : null;
|
13
|
+
}, Opal.global)
|
14
|
+
} else {
|
15
|
+
component = component_name;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
component = Isomorfeus.cached_component_class(component_name) unless component
|
19
|
+
Preact.render_to_string(Preact.create_element(component, `Opal.Hash.$new(props)`))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/isomorfeus-preact.rb
CHANGED
@@ -3,7 +3,6 @@ module LucidComponent::Initializer
|
|
3
3
|
@native = native_component
|
4
4
|
@app_store = LucidComponent::AppStoreProxy.new(self)
|
5
5
|
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self, @native)
|
6
|
-
@store = LucidComponent::InstanceStoreProxy.new(self)
|
7
6
|
@props = `Opal.Preact.Props.$new(#@native)`
|
8
7
|
@state = `Opal.Preact.State.$new(#@native)`
|
9
8
|
end
|
@@ -4,6 +4,5 @@ module LucidFunc::Initializer
|
|
4
4
|
@native_props = `Opal.Preact.Props.$new(#{self})`
|
5
5
|
@app_store = LucidComponent::AppStoreProxy.new(self)
|
6
6
|
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self, self)
|
7
|
-
@store = LucidComponent::InstanceStoreProxy.new(self)
|
8
7
|
end
|
9
8
|
end
|
data/lib/lucid_app/context.rb
CHANGED
@@ -5,7 +5,7 @@ module LucidApp
|
|
5
5
|
css_server = `null`
|
6
6
|
css_server = `document.getElementById('css-server-side')` unless on_ssr?
|
7
7
|
%x{
|
8
|
-
n = Opal.NanoCSS;
|
8
|
+
let n = Opal.NanoCSS;
|
9
9
|
nano_css = (css_server) ? n.create({ sh: css_server }) : n.create();
|
10
10
|
n.rule(nano_css);
|
11
11
|
n.sheet(nano_css);
|
data/lib/nano_css.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
module NanoCSS
|
2
2
|
%x{
|
3
3
|
var KEBAB_REGEX = /[A-Z]/g;
|
4
|
+
var on_browser = #{on_browser?};
|
5
|
+
var in_dev = #{Isomorfeus.development?};
|
4
6
|
|
5
7
|
function hash(str) {
|
6
8
|
var h = 5381, i = str.length;
|
7
9
|
while (i) h = (h * 33) ^ str.charCodeAt(--i);
|
8
10
|
return '_' + (h >>> 0).toString(36);
|
9
11
|
};
|
10
|
-
}
|
11
12
|
|
12
|
-
%x{
|
13
13
|
self.create = function (config) {
|
14
14
|
config = config || {};
|
15
15
|
var assign = config.assign || Object.assign;
|
16
16
|
var client = typeof window === 'object';
|
17
17
|
|
18
18
|
// Check if we are really in browser environment.
|
19
|
-
if (
|
19
|
+
if (on_browser && in_dev) {
|
20
20
|
if (client) {
|
21
21
|
if ((typeof document !== 'object') || !document.getElementsByTagName('HTML')) {
|
22
22
|
console.error('nano-css detected browser environment because of "window" global, but "document" global seems to be defective.');
|
@@ -47,7 +47,7 @@ module NanoCSS
|
|
47
47
|
if (renderer.client) {
|
48
48
|
if (!renderer.sh) { document.head.appendChild(renderer.sh = document.createElement('style')); }
|
49
49
|
|
50
|
-
if (
|
50
|
+
if (in_dev) {
|
51
51
|
renderer.sh.setAttribute('data-nano-css-dev', '');
|
52
52
|
|
53
53
|
// Test style sheet used in DEV mode to test if .insetRule() would throw.
|
@@ -60,7 +60,7 @@ module NanoCSS
|
|
60
60
|
// .insertRule() is faster than .appendChild(), that's why we use it in PROD.
|
61
61
|
// But CSS injected using .insertRule() is not displayed in Chrome Devtools
|
62
62
|
var sheet = renderer.sh.sheet;
|
63
|
-
if (
|
63
|
+
if (!in_dev) {
|
64
64
|
// Unknown pseudo-selectors will throw, this try/catch swallows all errors.
|
65
65
|
try { sheet.insertRule(rawCssRule, sheet.cssRules.length); }
|
66
66
|
catch (error) {}
|
@@ -91,7 +91,7 @@ module NanoCSS
|
|
91
91
|
if ((value instanceof Object) && !(value instanceof Array)) {
|
92
92
|
postponed.push(prop);
|
93
93
|
} else {
|
94
|
-
if (
|
94
|
+
if (in_dev && !renderer.sourcemaps) {
|
95
95
|
str += ' ' + renderer.decl(prop, value, selector, atrule) + '\n';
|
96
96
|
} else {
|
97
97
|
str += renderer.decl(prop, value, selector, atrule);
|
@@ -100,7 +100,7 @@ module NanoCSS
|
|
100
100
|
}
|
101
101
|
|
102
102
|
if (str) {
|
103
|
-
if (
|
103
|
+
if (in_dev && !renderer.sourcemaps) {
|
104
104
|
str = '\n' + selector + ' {\n' + str + '}\n';
|
105
105
|
} else {
|
106
106
|
str = selector + '{' + str + '}';
|
@@ -129,7 +129,7 @@ module NanoCSS
|
|
129
129
|
|
130
130
|
%x{
|
131
131
|
self.rule = function (renderer) {
|
132
|
-
if (
|
132
|
+
if (in_dev) {
|
133
133
|
renderer.rule_blocks = {};
|
134
134
|
}
|
135
135
|
|
@@ -142,7 +142,7 @@ module NanoCSS
|
|
142
142
|
|
143
143
|
renderer.rule = function (css, block) {
|
144
144
|
// Warn user if CSS selectors clash.
|
145
|
-
if (
|
145
|
+
if (in_dev) {
|
146
146
|
if (block) {
|
147
147
|
if (typeof block !== 'string') {
|
148
148
|
throw new TypeError(
|
@@ -194,7 +194,7 @@ module NanoCSS
|
|
194
194
|
var onElementModifier = function (elementModifier) {
|
195
195
|
var styles = map[elementModifier];
|
196
196
|
|
197
|
-
if (
|
197
|
+
if (in_dev && renderer.sourcemaps) {
|
198
198
|
// In dev mode emit CSS immediately to generate sourcemaps.
|
199
199
|
result[elementModifier] = renderer.rule(styles, block + '-' + elementModifier);
|
200
200
|
} else {
|
data/lib/preact/version.rb
CHANGED
data/lib/preact.rb
CHANGED
@@ -196,11 +196,12 @@ module Preact
|
|
196
196
|
};
|
197
197
|
|
198
198
|
self.internal_render = function(component, props, string_child, block) {
|
199
|
+
const oper = Opal.global.Preact;
|
199
200
|
const operabu = self.render_buffer;
|
200
201
|
let native_props;
|
201
202
|
if (props && props !== nil) { native_props = self.to_native_preact_props(props); }
|
202
203
|
if (string_child) {
|
203
|
-
operabu[operabu.length - 1].push(
|
204
|
+
operabu[operabu.length - 1].push(oper.createElement(component, native_props, string_child));
|
204
205
|
} else if (block && block !== nil) {
|
205
206
|
operabu.push([]);
|
206
207
|
// console.log("internal_render pushed", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
@@ -208,9 +209,9 @@ module Preact
|
|
208
209
|
if (block_result && block_result !== nil) { Opal.Preact.render_block_result(block_result); }
|
209
210
|
// console.log("internal_render popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
210
211
|
let children = operabu.pop();
|
211
|
-
operabu[operabu.length - 1].push(
|
212
|
+
operabu[operabu.length - 1].push(oper.createElement.apply(this, [component, native_props].concat(children)));
|
212
213
|
} else {
|
213
|
-
operabu[operabu.length - 1].push(
|
214
|
+
operabu[operabu.length - 1].push(oper.createElement(component, native_props));
|
214
215
|
}
|
215
216
|
};
|
216
217
|
|
@@ -4,9 +4,9 @@
|
|
4
4
|
"requires": true,
|
5
5
|
"packages": {
|
6
6
|
"node_modules/preact": {
|
7
|
-
"version": "10.6.
|
8
|
-
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.
|
9
|
-
"integrity": "sha512-
|
7
|
+
"version": "10.6.6",
|
8
|
+
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.6.tgz",
|
9
|
+
"integrity": "sha512-dgxpTFV2vs4vizwKohYKkk7g7rmp1wOOcfd4Tz3IB3Wi+ivZzsn/SpeKJhRENSE+n8sUfsAl4S3HiCVT923ABw==",
|
10
10
|
"funding": {
|
11
11
|
"type": "opencollective",
|
12
12
|
"url": "https://opencollective.com/preact"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015-present Jason Miller
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|