rails-react-views 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a028f3d9ae7fd27788a2562640ed586391a6ad570f7819dd3b856fb17ede47fd
4
+ data.tar.gz: 69c77a908ef892d597c51ca3c147d2d1cc8484569c4459fa2d9e26774a5759f7
5
+ SHA512:
6
+ metadata.gz: ece3d02d088046ce4a5d3fb9fe7553307e18d06782ef1f9c51de8b06a4369ad788cbbe1bfbb01b2347cd380ad08f387cdff499bc11c2d8312edfd1a168f2cc8b
7
+ data.tar.gz: e18d0f3068ee08ac8d975b7f838734cd9c265f9308829e32cab2cf49608ac7d609c77813e2f404895f690e7f9f7b39988a311f8970ae702724091a023c7261e8
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ ../LICENSE
data/README.md ADDED
@@ -0,0 +1 @@
1
+ ../README.md
@@ -0,0 +1,9 @@
1
+ require 'rails_react_views/concern'
2
+ require 'rails_react_views/config'
3
+ require 'rails_react_views/digest'
4
+ require 'rails_react_views/prerenderer'
5
+ require 'rails_react_views/railtie'
6
+ require 'rails_react_views/version'
7
+
8
+ module RailsReactViews
9
+ end
@@ -0,0 +1,30 @@
1
+ module RailsReactViews
2
+ module Concern
3
+ extend ActiveSupport::Concern
4
+
5
+ def render_react_view(view: nil, props: {}, prerender: true, cache: true, layout: nil)
6
+ view ||= "#{controller_path}/#{action_name}"
7
+ layout ||= RailsReactViews::config[:layout]
8
+ context = RailsReactViews::Prerenderer.build_context(view: view, props: props, path: request.path)
9
+
10
+ respond_to do |format|
11
+ format.html do
12
+ context_json = context.to_json
13
+ response = prerender ? RailsReactViews::Prerenderer.prerender(context_json: context_json, cache: cache) : {}
14
+ @head = response[:head]
15
+ @body = response[:body]
16
+ @body_with_state = "<div id=\"rails-react-view\">#{@body}</div>\n<script>window.__RAILS_REACT_VIEW_CONTEXT__ = #{context_json}</script>".html_safe
17
+
18
+ render inline: "<%= content_for :head, @head %><%= @body_with_state %>", layout: layout
19
+ end
20
+
21
+ format.json do
22
+ render json: {
23
+ **context,
24
+ '__type': 'RailsReactView'
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ module RailsReactViews
2
+ def self.config
3
+ @@config ||= begin
4
+ config =
5
+ if Rails.env.production?
6
+ `NODE_ENV=production node node_modules/rails-react-views/dist/cjs/server/scripts/config.js`
7
+ else
8
+ `BABEL_ENV=test node_modules/.bin/babel-node -x '.js,.jsx,.ts,.tsx' node_modules/rails-react-views/dist/cjs/server/scripts/config.js`
9
+ end
10
+
11
+ JSON.parse(config).with_indifferent_access
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module RailsReactViews
2
+ def self.digest
3
+ if Rails.env.production?
4
+ @@digest ||= calculate_digest
5
+ else
6
+ calculate_digest
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def self.calculate_digest
13
+ js_files = Dir.glob(Rails.root.join('app/javascript/**/*')).reject { |file| File.directory?(file) }
14
+ yarn_digest = Digest::MD5.file(Rails.root.join('yarn.lock'))
15
+ digests = js_files.map { |file| Digest::MD5.file(file).to_s } << yarn_digest
16
+
17
+ Digest::MD5.hexdigest(digests.to_s)
18
+ end
19
+ end
@@ -0,0 +1,110 @@
1
+ module RailsReactViews
2
+ class Prerenderer
3
+ class << self
4
+ def prerender(view: '', path: '', props: {}, context: nil, context_json: nil, cache: true)
5
+ context_json ||= (context || build_context(props: props, view: view, path: path)).to_json
6
+
7
+ if cache && Rails.configuration.action_controller.perform_caching
8
+ context_digest = Digest::MD5.hexdigest(context_json)
9
+
10
+ Rails.cache.fetch([RailsReactViews::digest, :rails_react_views, :prerenderer, :prerender, context_digest]) do
11
+ process_prerender(context_json)
12
+ end
13
+ else
14
+ process_prerender(context_json)
15
+ end
16
+ end
17
+
18
+ def build_context(props: {}, view:, path:)
19
+ {
20
+ props: props,
21
+ view: view,
22
+ path: base_path(path)
23
+ }
24
+ end
25
+
26
+ private
27
+
28
+ def process_prerender(context_json)
29
+ if server?
30
+ begin
31
+ server_prerender(context_json)
32
+ rescue
33
+ cmd? ? cmd_prerender(context_json) : {}
34
+ end
35
+ elsif cmd?
36
+ cmd_prerender(context_json)
37
+ else
38
+ {}
39
+ end
40
+ end
41
+
42
+ def server_prerender(context_json)
43
+ port = RailsReactViews::config[:port]
44
+ response = HTTParty.post("http://localhost:#{port}", body: { context: context_json })
45
+
46
+ html = response.success? ? response.body : ''
47
+ split_html(html)
48
+ end
49
+
50
+ def cmd_prerender(context_json)
51
+ encoded_context = encode_text(context_json)
52
+ encoded_html =
53
+ if Rails.env.production?
54
+ `NODE_ENV=production node node_modules/rails-react-views/dist/cjs/server/scripts/cmd.js #{encoded_context}`
55
+ else
56
+ `BABEL_ENV=test node_modules/.bin/babel-node -x '.js,.jsx,.ts,.tsx' node_modules/rails-react-views/dist/cjs/server/scripts/cmd.js #{encoded_context}`
57
+ end
58
+
59
+ html = decode_text(encoded_html)
60
+ split_html(html)
61
+ end
62
+
63
+ def encode_text(text)
64
+ gzipped_text = Zlib::Deflate.deflate(text)
65
+ Base64.strict_encode64(gzipped_text)
66
+ end
67
+
68
+ def decode_text(text)
69
+ decoded_text = Base64.strict_decode64(text)
70
+ Zlib::Inflate.inflate(decoded_text).force_encoding('utf-8')
71
+ end
72
+
73
+ def base_path(path)
74
+ if path.ends_with?('.json')
75
+ path[0..-6]
76
+ else
77
+ path
78
+ end
79
+ end
80
+
81
+ def split_html(html = '')
82
+ head_start = html.index('<head>')
83
+ head_end = html.index('</head>')
84
+ head = (head_start && head_end ? html[head_start + 6..head_end - 1] : '').html_safe
85
+
86
+ body_start = html.index('<body>')
87
+ body_end = html.index('</body>')
88
+ body = (body_start && body_end ? html[body_start + 6..body_end - 1] : '').html_safe
89
+
90
+ { head: head, body: body }
91
+ end
92
+
93
+ def server?
94
+ RailsReactViews::config[:server]
95
+ end
96
+
97
+ def cmd?
98
+ RailsReactViews::config[:cmd]
99
+ end
100
+
101
+ def server_up?
102
+ port = RailsReactViews::config[:port]
103
+ response = HTTParty.get("http://localhost:#{port}/ping")
104
+ response.code == 200
105
+ rescue
106
+ false
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,12 @@
1
+ module RailsReactViews
2
+ class Railtie < Rails::Railtie
3
+ initializer "railtie.initializer" do
4
+ RailsReactViews.config
5
+ RailsReactViews.digest
6
+
7
+ ActiveSupport.on_load(:action_controller) do
8
+ include RailsReactViews::Concern
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module RailsReactViews
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-react-views
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Geerts
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: webpacker
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ description: A library for full integration of React.js views in Ruby on Rails.
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - lib/rails-react-views.rb
50
+ - lib/rails_react_views/concern.rb
51
+ - lib/rails_react_views/config.rb
52
+ - lib/rails_react_views/digest.rb
53
+ - lib/rails_react_views/prerenderer.rb
54
+ - lib/rails_react_views/railtie.rb
55
+ - lib/rails_react_views/version.rb
56
+ homepage: https://rubygems.org/gems/rails-react-views
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubygems_version: 3.1.6
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: React.js views for Ruby on Rails
79
+ test_files: []