Skip to content

Commit 14ecdfb

Browse files
BrandonSharBrandon Shar
and
Brandon Shar
authored
Inertia SSR (#74)
* wip * bugfix and better naming * Add test Co-authored-by: Brandon Shar <[email protected]>
1 parent b78d791 commit 14ecdfb

File tree

6 files changed

+81
-0
lines changed

6 files changed

+81
-0
lines changed

lib/inertia_rails/controller.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require_relative "inertia_rails"
2+
require_relative "helper"
23

34
module InertiaRails
45
module Controller
@@ -9,6 +10,7 @@ module Controller
910
# :inertia_errors are deleted from the session by the middleware
1011
InertiaRails.share(errors: session[:inertia_errors]) if session[:inertia_errors].present?
1112
end
13+
helper ::InertiaRails::Helper
1214
end
1315

1416
module ClassMethods

lib/inertia_rails/helper.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require_relative 'inertia_rails'
2+
3+
module InertiaRails::Helper
4+
def inertia_headers
5+
::InertiaRails.html_headers.join.html_safe
6+
end
7+
end

lib/inertia_rails/inertia_rails.rb

+20
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
module InertiaRails
66
thread_mattr_accessor :threadsafe_shared_plain_data
77
thread_mattr_accessor :threadsafe_shared_blocks
8+
thread_mattr_accessor :threadsafe_html_headers
89

910
def self.configure
1011
yield(Configuration)
@@ -23,6 +24,18 @@ def self.layout
2324
Configuration.layout
2425
end
2526

27+
def self.ssr_enabled?
28+
Configuration.ssr_enabled
29+
end
30+
31+
def self.ssr_url
32+
Configuration.ssr_url
33+
end
34+
35+
def self.html_headers
36+
self.threadsafe_html_headers || []
37+
end
38+
2639
# "Setters"
2740
def self.share(**args)
2841
self.shared_plain_data = self.shared_plain_data.merge(args)
@@ -32,9 +45,14 @@ def self.share_block(block)
3245
self.shared_blocks = self.shared_blocks + [block]
3346
end
3447

48+
def self.html_headers=(headers)
49+
self.threadsafe_html_headers = headers
50+
end
51+
3552
def self.reset!
3653
self.shared_plain_data = {}
3754
self.shared_blocks = []
55+
self.html_headers = []
3856
end
3957

4058
def self.lazy(value = nil, &block)
@@ -46,6 +64,8 @@ def self.lazy(value = nil, &block)
4664
module Configuration
4765
mattr_accessor(:layout) { 'application' }
4866
mattr_accessor(:version) { nil }
67+
mattr_accessor(:ssr_enabled) { false }
68+
mattr_accessor(:ssr_url) { 'http://localhost:13714' }
4969

5070
def self.evaluated_version
5171
self.version.respond_to?(:call) ? self.version.call : self.version

lib/inertia_rails/renderer.rb

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'net/http'
2+
require 'json'
13
require_relative "inertia_rails"
24

35
module InertiaRails
@@ -15,6 +17,8 @@ def initialize(component, controller, request, response, render_method, props:,
1517
end
1618

1719
def render
20+
return render_ssr if ::InertiaRails.ssr_enabled?
21+
1822
if @request.headers['X-Inertia']
1923
@response.set_header('Vary', 'Accept')
2024
@response.set_header('X-Inertia', 'true')
@@ -26,6 +30,14 @@ def render
2630

2731
private
2832

33+
def render_ssr
34+
uri = URI("#{::InertiaRails.ssr_url}/render")
35+
res = JSON.parse(Net::HTTP.post(uri, page.to_json, 'Content-Type' => 'application/json').body)
36+
37+
::InertiaRails.html_headers = res['head']
38+
@render_method.call html: res['body'].html_safe, layout: ::InertiaRails.layout, locals: (view_data).merge({page: page})
39+
end
40+
2941
def props
3042
_props = ::InertiaRails.shared_data(@controller).merge(@props).select do |key, prop|
3143
if rendering_partial_component?
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
<%= inertia_headers %>
12
<%= yield %>
23
<%= local_assigns.except(:page).to_json.html_safe %>

spec/inertia/ssr_spec.rb

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
RSpec.describe 'inertia ssr', type: :request do
2+
context 'ssr is enabled' do
3+
before do
4+
InertiaRails.reset!
5+
InertiaRails.configure do |config|
6+
config.ssr_enabled = true
7+
config.ssr_url = 'ssr-url'
8+
config.version = '1.0'
9+
end
10+
end
11+
12+
it 'returns the result of the ssr call' do
13+
allow(Net::HTTP).to receive(:post)
14+
.with(
15+
URI('ssr-url/render'),
16+
{
17+
component: 'TestComponent',
18+
props: {name: 'Brandon', sport: 'hockey'},
19+
url: props_path,
20+
version: '1.0',
21+
}.to_json,
22+
'Content-Type' => 'application/json'
23+
)
24+
.and_return(OpenStruct.new(
25+
body: {
26+
body: '<div>Test works</div>',
27+
head: ['<title>Title works</title>'],
28+
}.to_json
29+
))
30+
31+
32+
get props_path
33+
34+
35+
expect(response.body).to include('<title>Title works</title>')
36+
expect(response.body).to include('<div>Test works</div>')
37+
end
38+
end
39+
end

0 commit comments

Comments
 (0)