19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
# File 'lib/isomorfeus/preact_view_helper.rb', line 19
def mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4)
ssr_start_time = Time.now if Isomorfeus.development?
@ssr_response_status = nil
@ssr_styles = nil
render_result = "<div data-iso-env=\"#{Isomorfeus.env}\" data-iso-root=\"#{component_name}\" data-iso-props='#{Oj.dump(props, mode: :strict)}'"
if !skip_ssr && (Isomorfeus.server_side_rendering || use_ssr)
thread_id_asset = "#{Thread.current.object_id}|#{asset_key}"
begin
init_speednode_context(asset_key, thread_id_asset) if Isomorfeus.development? || !Isomorfeus.ssr_contexts.key?(thread_id_asset)
rescue Exception => e
Isomorfeus.raise_error(message: "Server Side Rendering: Failed creating context for #{asset_key}. Error: #{e.message}", stack: e.backtrace)
end
ctx = Isomorfeus.ssr_contexts[thread_id_asset]
pass = 0
ws_scheme = props[:location_scheme] == 'https:' ? 'wss:' : 'ws:'
location_host = props[:location_host] ? props[:location_host] : 'localhost'
api_ws_path = Isomorfeus.respond_to?(:api_websocket_path) ? Isomorfeus.api_websocket_path : ''
transport_ws_url = ws_scheme + location_host + api_ws_path
javascript = <<~JAVASCRIPT
return Opal.Isomorfeus.SSR.mount_component('#{Thread.current[:isomorfeus_session_id]}', '#{Isomorfeus.env}', '#{props[:locale]}', '#{transport_ws_url}', '#{component_name}', #{Oj.dump(props, mode: :strict)}, #{max_passes})
JAVASCRIPT
begin
ctx.exec(javascript)
rescue Exception => e
Isomorfeus.raise_error(error: e)
end
sleep 0.001 rendering = ctx.eval_script(key: :rendering)
if rendering
start_time = Time.now
while rendering
break if (Time.now - start_time) > 10
sleep 0.005
rendering = ctx.eval_script(key: :rendering)
end
end
rendered_tree, application_state, @ssr_styles, @ssr_response_status, passes, exception = ctx.eval_script(key: :get_result)
Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
render_result << " data-iso-hydrated='true'" if rendered_tree
if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
render_result << " data-iso-usid=#{Oj.dump(Isomorfeus.current_user.sid, mode: :strict)}"
end
render_result << " data-iso-nloc='#{props[:locale]}'>"
render_result << (rendered_tree ? rendered_tree : "SSR didn't work")
else
if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
render_result << " data-iso-usid=#{Oj.dump(Isomorfeus.current_user.sid, mode: :strict)}"
end
render_result << " data-iso-nloc='#{props[:locale]}'>"
end
render_result << '</div>'
if Isomorfeus.server_side_rendering && !skip_ssr
render_result = "<script type='application/javascript'>\nServerSideRenderingStateJSON = #{Oj.dump(application_state, mode: :strict)}\n</script>\n" << render_result
puts "PreactViewHelper Server Side Rendering rendered #{passes} passes and took ~#{((Time.now - ssr_start_time)*1000).to_i}ms" if Isomorfeus.development?
end
render_result
end
|