rails-react-views 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 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: []