react_on_rails 11.1.7 → 11.3.1.beta.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc +8 -2
- data/.prettierignore +1 -0
- data/.prettierrc +20 -0
- data/.release-it.json +3 -0
- data/.travis.yml +10 -9
- data/CHANGELOG.md +60 -3
- data/CONTRIBUTING.md +2 -10
- data/Gemfile +1 -2
- data/Gemfile.rails32 +0 -1
- data/README.md +30 -14
- data/SUMMARY.md +6 -2
- data/docs/additional-reading/{hot-reloading-rails-development.md → hot-reloading-rails-development-asset-pipeline.md} +2 -12
- data/docs/additional-reading/images.md +1 -1
- data/docs/additional-reading/rails_view_rendering_from_inline_javascript.md +2 -1
- data/docs/additional-reading/upgrade-webpacker-v3-to-v4.md +10 -0
- data/docs/api/view-helpers-api.md +12 -8
- data/docs/basics/configuration.md +4 -4
- data/docs/basics/generator-details.md +1 -1
- data/docs/basics/minitest-configuration.md +31 -0
- data/docs/basics/react-server-rendering.md +3 -1
- data/docs/basics/recommended-project-structure.md +24 -1
- data/docs/basics/rspec-configuration.md +2 -2
- data/docs/basics/upgrading-react-on-rails.md +11 -1
- data/docs/basics/webpack-configuration.md +11 -0
- data/docs/misc-pending/code-splitting.md +2 -2
- data/docs/misc-pending/manual-installation-overview.md +1 -1
- data/docs/testimonials/hvmn.md +25 -0
- data/docs/testimonials/resortpass.md +13 -0
- data/docs/testimonials/testimonials.md +28 -0
- data/docs/tutorial.md +123 -11
- data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -0
- data/lib/generators/react_on_rails/install_generator.rb +2 -0
- data/lib/react_on_rails.rb +1 -0
- data/lib/react_on_rails/assets_precompile.rb +3 -0
- data/lib/react_on_rails/configuration.rb +2 -1
- data/lib/react_on_rails/git_utils.rb +2 -0
- data/lib/react_on_rails/helper.rb +71 -70
- data/lib/react_on_rails/json_output.rb +1 -1
- data/lib/react_on_rails/locales_to_js.rb +2 -0
- data/lib/react_on_rails/react_component/render_options.rb +4 -0
- data/lib/react_on_rails/server_rendering_js_code.rb +42 -0
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +44 -14
- data/lib/react_on_rails/utils.rb +5 -1
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +4 -1
- data/lib/react_on_rails/webpacker_utils.rb +9 -1
- data/package-scripts.yml +46 -0
- data/package.json +24 -15
- data/rakelib/release.rake +3 -2
- data/react_on_rails.gemspec +1 -1
- data/webpackConfigLoader.js +2 -2
- data/yarn.lock +4431 -1689
- metadata +18 -10
- data/docs/testimonials.md +0 -11
@@ -36,6 +36,7 @@ module ReactOnRails
|
|
36
36
|
|
37
37
|
def replace_prerender_if_server_rendering
|
38
38
|
return unless options.example_server_rendering
|
39
|
+
|
39
40
|
hello_world_index = File.join(destination_root, "app", "views", "hello_world", "index.html.erb")
|
40
41
|
hello_world_contents = File.read(hello_world_index)
|
41
42
|
new_hello_world_contents = hello_world_contents.gsub(/prerender: false/,
|
@@ -62,6 +62,7 @@ module ReactOnRails
|
|
62
62
|
|
63
63
|
def missing_yarn?
|
64
64
|
return false unless ReactOnRails::Utils.running_on_windows? ? `where yarn`.blank? : `which yarn`.blank?
|
65
|
+
|
65
66
|
error = "yarn is required. Please install it before continuing. https://yarnpkg.com/en/docs/install"
|
66
67
|
GeneratorMessages.add_error(error)
|
67
68
|
true
|
@@ -69,6 +70,7 @@ module ReactOnRails
|
|
69
70
|
|
70
71
|
def missing_node?
|
71
72
|
return false unless ReactOnRails::Utils.running_on_windows? ? `where node`.blank? : `which node`.blank?
|
73
|
+
|
72
74
|
error = "** nodejs is required. Please install it before continuing. https://nodejs.org/en/"
|
73
75
|
GeneratorMessages.add_error(error)
|
74
76
|
true
|
data/lib/react_on_rails.rb
CHANGED
@@ -11,6 +11,7 @@ require "react_on_rails/version"
|
|
11
11
|
require "react_on_rails/version_checker"
|
12
12
|
require "react_on_rails/configuration"
|
13
13
|
require "react_on_rails/server_rendering_pool"
|
14
|
+
require "react_on_rails/server_rendering_js_code"
|
14
15
|
require "react_on_rails/engine"
|
15
16
|
require "react_on_rails/react_component/render_options"
|
16
17
|
require "react_on_rails/version_syntax_converter"
|
@@ -64,6 +64,7 @@ module ReactOnRails
|
|
64
64
|
# references from webpack's CSS would be invalid. The fix is to symlink the double-digested
|
65
65
|
# file back to the original digested name, and make a similar symlink for the gz version.
|
66
66
|
return unless @symlink_non_digested_assets_regex
|
67
|
+
|
67
68
|
manifest_glob = Dir.glob(@assets_path.join(".sprockets-manifest-*.json")) +
|
68
69
|
Dir.glob(@assets_path.join("manifest-*.json")) +
|
69
70
|
Dir.glob(@assets_path.join("manifest.yml"))
|
@@ -86,6 +87,7 @@ module ReactOnRails
|
|
86
87
|
manifest_data.each do |original_filename, rails_digested_filename|
|
87
88
|
# TODO: we should remove any original_filename that is NOT in the webpack deploy folder.
|
88
89
|
next unless original_filename =~ @symlink_non_digested_assets_regex
|
90
|
+
|
89
91
|
# We're symlinking from the digested filename back to the original filename which has
|
90
92
|
# already been symlinked by Webpack
|
91
93
|
symlink_file(rails_digested_filename, original_filename)
|
@@ -100,6 +102,7 @@ module ReactOnRails
|
|
100
102
|
def delete_broken_symlinks
|
101
103
|
Dir.glob(@assets_path.join("*")).each do |filename|
|
102
104
|
next unless File.lstat(filename).symlink?
|
105
|
+
|
103
106
|
begin
|
104
107
|
target = File.readlink(filename)
|
105
108
|
rescue StandardError
|
@@ -21,7 +21,7 @@ module ReactOnRails
|
|
21
21
|
prerender: false,
|
22
22
|
replay_console: true,
|
23
23
|
logging_on_server: true,
|
24
|
-
raise_on_prerender_error:
|
24
|
+
raise_on_prerender_error: Rails.env.development?,
|
25
25
|
trace: Rails.env.development?,
|
26
26
|
development_mode: Rails.env.development?,
|
27
27
|
server_renderer_pool_size: DEFAULT_POOL_SIZE,
|
@@ -218,6 +218,7 @@ module ReactOnRails
|
|
218
218
|
|
219
219
|
def configure_skip_display_none_deprecation
|
220
220
|
return if skip_display_none.nil?
|
221
|
+
|
221
222
|
Rails.logger.warn "[DEPRECATION] ReactOnRails: remove skip_display_none from configuration."
|
222
223
|
end
|
223
224
|
end
|
@@ -6,8 +6,10 @@ module ReactOnRails
|
|
6
6
|
module GitUtils
|
7
7
|
def self.uncommitted_changes?(message_handler)
|
8
8
|
return false if ENV["COVERAGE"] == "true"
|
9
|
+
|
9
10
|
status = `git status --porcelain`
|
10
11
|
return false if $CHILD_STATUS.success? && status.empty?
|
12
|
+
|
11
13
|
error = if !$CHILD_STATUS.success?
|
12
14
|
"You do not have Git installed. Please install Git, and commit your changes before continuing"
|
13
15
|
else
|
@@ -136,7 +136,7 @@ module ReactOnRails
|
|
136
136
|
# It is exactly like react_component except for the following:
|
137
137
|
# 1. prerender: true is automatically added, as this method doesn't make sense for client only
|
138
138
|
# rendering.
|
139
|
-
# 2. Your JavaScript for server rendering must return an Object
|
139
|
+
# 2. Your JavaScript generator function for server rendering must return an Object rather than a React component.
|
140
140
|
# 3. Your view code must expect an object and not a string.
|
141
141
|
#
|
142
142
|
# Here is an example of the view code:
|
@@ -206,6 +206,7 @@ module ReactOnRails
|
|
206
206
|
# that contains a data props.
|
207
207
|
def redux_store_hydration_data
|
208
208
|
return if @registered_stores_defer_render.blank?
|
209
|
+
|
209
210
|
@registered_stores_defer_render.reduce("".dup) do |accum, redux_store_data|
|
210
211
|
accum << render_redux_store_data(redux_store_data)
|
211
212
|
end.html_safe
|
@@ -265,6 +266,7 @@ module ReactOnRails
|
|
265
266
|
|
266
267
|
def json_safe_and_pretty(hash_or_string)
|
267
268
|
return "{}" if hash_or_string.nil?
|
269
|
+
|
268
270
|
unless hash_or_string.is_a?(String) || hash_or_string.is_a?(Hash)
|
269
271
|
raise ReactOnRails::Error, "#{__method__} only accepts String or Hash as argument "\
|
270
272
|
"(#{hash_or_string.class} given)."
|
@@ -275,6 +277,59 @@ module ReactOnRails
|
|
275
277
|
ReactOnRails::JsonOutput.escape(json_value)
|
276
278
|
end
|
277
279
|
|
280
|
+
# This is the definitive list of the default values used for the rails_context, which is the
|
281
|
+
# second parameter passed to both component and store generator functions.
|
282
|
+
# This method can be called from views and from the controller, as `helpers.rails_context`
|
283
|
+
#
|
284
|
+
# rubocop:disable Metrics/AbcSize
|
285
|
+
def rails_context(server_side: true)
|
286
|
+
@rails_context ||= begin
|
287
|
+
result = {
|
288
|
+
railsEnv: Rails.env,
|
289
|
+
inMailer: in_mailer?,
|
290
|
+
# Locale settings
|
291
|
+
i18nLocale: I18n.locale,
|
292
|
+
i18nDefaultLocale: I18n.default_locale,
|
293
|
+
rorVersion: ReactOnRails::VERSION,
|
294
|
+
rorPro: ReactOnRails::Utils.react_on_rails_pro?
|
295
|
+
}
|
296
|
+
if defined?(request) && request.present?
|
297
|
+
# Check for encoding of the request's original_url and try to force-encoding the
|
298
|
+
# URLs as UTF-8. This situation can occur in browsers that do not encode the
|
299
|
+
# entire URL as UTF-8 already, mostly on the Windows platform (IE11 and lower).
|
300
|
+
original_url_normalized = request.original_url
|
301
|
+
if original_url_normalized.encoding.to_s == "ASCII-8BIT"
|
302
|
+
original_url_normalized = original_url_normalized.force_encoding("ISO-8859-1").encode("UTF-8")
|
303
|
+
end
|
304
|
+
|
305
|
+
# Using Addressable instead of standard URI to better deal with
|
306
|
+
# non-ASCII characters (see https://github.com/shakacode/react_on_rails/pull/405)
|
307
|
+
uri = Addressable::URI.parse(original_url_normalized)
|
308
|
+
# uri = Addressable::URI.parse("http://foo.com:3000/posts?id=30&limit=5#time=1305298413")
|
309
|
+
|
310
|
+
result.merge!(
|
311
|
+
# URL settings
|
312
|
+
href: uri.to_s,
|
313
|
+
location: "#{uri.path}#{uri.query.present? ? "?#{uri.query}" : ''}",
|
314
|
+
scheme: uri.scheme, # http
|
315
|
+
host: uri.host, # foo.com
|
316
|
+
port: uri.port,
|
317
|
+
pathname: uri.path, # /posts
|
318
|
+
search: uri.query, # id=30&limit=5
|
319
|
+
httpAcceptLanguage: request.env["HTTP_ACCEPT_LANGUAGE"]
|
320
|
+
)
|
321
|
+
end
|
322
|
+
if ReactOnRails.configuration.rendering_extension
|
323
|
+
custom_context = ReactOnRails.configuration.rendering_extension.custom_context(self)
|
324
|
+
result.merge!(custom_context) if custom_context
|
325
|
+
end
|
326
|
+
result
|
327
|
+
end
|
328
|
+
|
329
|
+
@rails_context.merge(serverSide: server_side)
|
330
|
+
end
|
331
|
+
# rubocop:enable Metrics/AbcSize
|
332
|
+
|
278
333
|
private
|
279
334
|
|
280
335
|
def build_react_component_result_for_server_rendered_string(
|
@@ -284,9 +339,15 @@ module ReactOnRails
|
|
284
339
|
render_options: required("render_options")
|
285
340
|
)
|
286
341
|
content_tag_options = render_options.html_options
|
342
|
+
if content_tag_options.key?(:tag)
|
343
|
+
content_tag_options_html_tag = content_tag_options[:tag]
|
344
|
+
content_tag_options.delete(:tag)
|
345
|
+
else
|
346
|
+
content_tag_options_html_tag = "div"
|
347
|
+
end
|
287
348
|
content_tag_options[:id] = render_options.dom_id
|
288
349
|
|
289
|
-
rendered_output = content_tag(
|
350
|
+
rendered_output = content_tag(content_tag_options_html_tag.to_sym,
|
290
351
|
server_rendered_html.html_safe,
|
291
352
|
content_tag_options)
|
292
353
|
|
@@ -431,22 +492,13 @@ module ReactOnRails
|
|
431
492
|
#
|
432
493
|
# Read more here: http://timelessrepo.com/json-isnt-a-javascript-subset
|
433
494
|
|
434
|
-
|
435
|
-
|
436
|
-
(
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
name: '#{react_component_name}',
|
442
|
-
domNodeId: '#{render_options.dom_id}',
|
443
|
-
props: props,
|
444
|
-
trace: #{render_options.trace},
|
445
|
-
railsContext: railsContext
|
446
|
-
});
|
447
|
-
})()
|
448
|
-
JS
|
449
|
-
# rubocop:enable Layout/IndentHeredoc
|
495
|
+
js_code = ReactOnRails::ServerRenderingJsCode.server_rendering_component_js_code(
|
496
|
+
props_string: props_string(props).gsub("\u2028", '\u2028').gsub("\u2029", '\u2029'),
|
497
|
+
rails_context: rails_context(server_side: true).to_json,
|
498
|
+
redux_stores: initialize_redux_stores,
|
499
|
+
react_component_name: react_component_name,
|
500
|
+
render_options: render_options
|
501
|
+
)
|
450
502
|
|
451
503
|
begin
|
452
504
|
result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(js_code, render_options)
|
@@ -478,6 +530,7 @@ module ReactOnRails
|
|
478
530
|
JS
|
479
531
|
|
480
532
|
return result unless @registered_stores.present? || @registered_stores_defer_render.present?
|
533
|
+
|
481
534
|
declarations = "var reduxProps, store, storeGenerator;\n".dup
|
482
535
|
all_stores = (@registered_stores || []) + (@registered_stores_defer_render || [])
|
483
536
|
|
@@ -494,58 +547,6 @@ module ReactOnRails
|
|
494
547
|
result
|
495
548
|
end
|
496
549
|
|
497
|
-
# This is the definitive list of the default values used for the rails_context, which is the
|
498
|
-
# second parameter passed to both component and store generator functions.
|
499
|
-
# rubocop:disable Metrics/AbcSize
|
500
|
-
def rails_context(server_side: required("server_side"))
|
501
|
-
@rails_context ||= begin
|
502
|
-
result = {
|
503
|
-
railsEnv: Rails.env,
|
504
|
-
inMailer: in_mailer?,
|
505
|
-
# Locale settings
|
506
|
-
i18nLocale: I18n.locale,
|
507
|
-
i18nDefaultLocale: I18n.default_locale,
|
508
|
-
rorVersion: ReactOnRails::VERSION,
|
509
|
-
rorPro: ReactOnRails::Utils.react_on_rails_pro?
|
510
|
-
}
|
511
|
-
if defined?(request) && request.present?
|
512
|
-
# Check for encoding of the request's original_url and try to force-encoding the
|
513
|
-
# URLs as UTF-8. This situation can occur in browsers that do not encode the
|
514
|
-
# entire URL as UTF-8 already, mostly on the Windows platform (IE11 and lower).
|
515
|
-
original_url_normalized = request.original_url
|
516
|
-
if original_url_normalized.encoding.to_s == "ASCII-8BIT"
|
517
|
-
original_url_normalized = original_url_normalized.force_encoding("ISO-8859-1").encode("UTF-8")
|
518
|
-
end
|
519
|
-
|
520
|
-
# Using Addressable instead of standard URI to better deal with
|
521
|
-
# non-ASCII characters (see https://github.com/shakacode/react_on_rails/pull/405)
|
522
|
-
uri = Addressable::URI.parse(original_url_normalized)
|
523
|
-
# uri = Addressable::URI.parse("http://foo.com:3000/posts?id=30&limit=5#time=1305298413")
|
524
|
-
|
525
|
-
result.merge!(
|
526
|
-
# URL settings
|
527
|
-
href: uri.to_s,
|
528
|
-
location: "#{uri.path}#{uri.query.present? ? "?#{uri.query}" : ''}",
|
529
|
-
scheme: uri.scheme, # http
|
530
|
-
host: uri.host, # foo.com
|
531
|
-
port: uri.port,
|
532
|
-
pathname: uri.path, # /posts
|
533
|
-
search: uri.query, # id=30&limit=5
|
534
|
-
httpAcceptLanguage: request.env["HTTP_ACCEPT_LANGUAGE"]
|
535
|
-
)
|
536
|
-
end
|
537
|
-
if ReactOnRails.configuration.rendering_extension
|
538
|
-
custom_context = ReactOnRails.configuration.rendering_extension.custom_context(self)
|
539
|
-
result.merge!(custom_context) if custom_context
|
540
|
-
end
|
541
|
-
result
|
542
|
-
end
|
543
|
-
|
544
|
-
@rails_context.merge(serverSide: server_side)
|
545
|
-
end
|
546
|
-
|
547
|
-
# rubocop:enable Metrics/AbcSize
|
548
|
-
|
549
550
|
def replay_console_option(val)
|
550
551
|
val.nil? ? ReactOnRails.configuration.replay_console : val
|
551
552
|
end
|
@@ -11,7 +11,7 @@ module ReactOnRails
|
|
11
11
|
"\u2028" => '\u2028',
|
12
12
|
"\u2029" => '\u2029'
|
13
13
|
}.freeze
|
14
|
-
ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
14
|
+
ESCAPE_REGEXP = /[\u2028\u2029&><]/u.freeze
|
15
15
|
|
16
16
|
def self.escape(json)
|
17
17
|
return escape_without_erb_util(json) if Utils.rails_version_less_than_4_1_1
|
@@ -7,6 +7,7 @@ module ReactOnRails
|
|
7
7
|
def initialize
|
8
8
|
return if i18n_dir.nil?
|
9
9
|
return unless obsolete?
|
10
|
+
|
10
11
|
@translations, @defaults = generate_translations
|
11
12
|
convert
|
12
13
|
end
|
@@ -15,6 +16,7 @@ module ReactOnRails
|
|
15
16
|
|
16
17
|
def obsolete?
|
17
18
|
return true if exist_js_files.empty?
|
19
|
+
|
18
20
|
js_files_are_outdated
|
19
21
|
end
|
20
22
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReactOnRails
|
4
|
+
module ServerRenderingJsCode
|
5
|
+
class << self
|
6
|
+
def js_code_renderer
|
7
|
+
@js_code_renderer ||= if ReactOnRails::Utils.react_on_rails_pro?
|
8
|
+
ReactOnRailsPro::ServerRenderingJsCode
|
9
|
+
else
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def server_rendering_component_js_code(
|
15
|
+
props_string: nil,
|
16
|
+
rails_context: nil,
|
17
|
+
redux_stores: nil,
|
18
|
+
react_component_name: nil,
|
19
|
+
render_options: nil
|
20
|
+
)
|
21
|
+
js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def render(props_string, rails_context, redux_stores, react_component_name, render_options)
|
25
|
+
<<-JS
|
26
|
+
(function() {
|
27
|
+
var railsContext = #{rails_context};
|
28
|
+
#{redux_stores}
|
29
|
+
var props = #{props_string};
|
30
|
+
return ReactOnRails.serverRenderReactComponent({
|
31
|
+
name: '#{react_component_name}',
|
32
|
+
domNodeId: '#{render_options.dom_id}',
|
33
|
+
props: props,
|
34
|
+
trace: #{render_options.trace},
|
35
|
+
railsContext: railsContext
|
36
|
+
});
|
37
|
+
})()
|
38
|
+
JS
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,7 +4,9 @@ require "open-uri"
|
|
4
4
|
|
5
5
|
module ReactOnRails
|
6
6
|
module ServerRenderingPool
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
7
8
|
class RubyEmbeddedJavaScript
|
9
|
+
# rubocop:enable Metrics/ClassLength
|
8
10
|
class << self
|
9
11
|
def reset_pool
|
10
12
|
options = {
|
@@ -17,12 +19,17 @@ module ReactOnRails
|
|
17
19
|
def reset_pool_if_server_bundle_was_modified
|
18
20
|
return unless ReactOnRails.configuration.development_mode
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
return if @server_bundle_timestamp == file_mtime
|
22
|
+
if ReactOnRails::Utils.server_bundle_path_is_http?
|
23
|
+
return if @server_bundle_url == ReactOnRails::Utils.server_bundle_js_file_path
|
23
24
|
|
24
|
-
|
25
|
+
@server_bundle_url = ReactOnRails::Utils.server_bundle_js_file_path
|
26
|
+
else
|
27
|
+
file_mtime = File.mtime(ReactOnRails::Utils.server_bundle_js_file_path)
|
28
|
+
@server_bundle_timestamp ||= file_mtime
|
29
|
+
return if @server_bundle_timestamp == file_mtime
|
25
30
|
|
31
|
+
@server_bundle_timestamp = file_mtime
|
32
|
+
end
|
26
33
|
ReactOnRails::ServerRenderingPool.reset_pool
|
27
34
|
end
|
28
35
|
|
@@ -72,6 +79,7 @@ module ReactOnRails
|
|
72
79
|
|
73
80
|
def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
|
74
81
|
return unless ReactOnRails.configuration.trace || force
|
82
|
+
|
75
83
|
# Set to anything to print generated code.
|
76
84
|
File.write(file_name, js_code)
|
77
85
|
msg = <<-MSG.strip_heredoc
|
@@ -95,19 +103,25 @@ module ReactOnRails
|
|
95
103
|
end
|
96
104
|
end
|
97
105
|
|
106
|
+
def read_bundle_js_code
|
107
|
+
server_js_file = ReactOnRails::Utils.server_bundle_js_file_path
|
108
|
+
if ReactOnRails::Utils.server_bundle_path_is_http?
|
109
|
+
file_url_to_string(server_js_file)
|
110
|
+
else
|
111
|
+
File.read(server_js_file)
|
112
|
+
end
|
113
|
+
rescue StandardError => e
|
114
|
+
msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be "\
|
115
|
+
"read. You may set the server_bundle_js_file in your configuration to be \"\" to "\
|
116
|
+
"avoid this warning.\nError is: #{e}"
|
117
|
+
raise ReactOnRails::Error, msg
|
118
|
+
end
|
119
|
+
|
98
120
|
def create_js_context
|
99
121
|
return if ReactOnRails.configuration.server_bundle_js_file.blank?
|
100
122
|
|
101
|
-
|
123
|
+
bundle_js_code = read_bundle_js_code
|
102
124
|
|
103
|
-
begin
|
104
|
-
bundle_js_code = File.read(server_js_file)
|
105
|
-
rescue StandardError => e
|
106
|
-
msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be "\
|
107
|
-
"read. You may set the server_bundle_js_file in your configuration to be \"\" to "\
|
108
|
-
"avoid this warning.\nError is: #{e}"
|
109
|
-
raise ReactOnRails::Error, msg
|
110
|
-
end
|
111
125
|
# rubocop:disable Layout/IndentHeredoc
|
112
126
|
base_js_code = <<-JS
|
113
127
|
#{console_polyfill}
|
@@ -118,7 +132,10 @@ module ReactOnRails
|
|
118
132
|
file_name = "tmp/base_js_code.js"
|
119
133
|
begin
|
120
134
|
if ReactOnRails.configuration.trace
|
121
|
-
Rails.logger.info
|
135
|
+
Rails.logger.info do
|
136
|
+
"[react_on_rails] Created JavaScript context with file "\
|
137
|
+
"#{ReactOnRails::Utils.server_bundle_js_file_path}"
|
138
|
+
end
|
122
139
|
end
|
123
140
|
ExecJS.compile(base_js_code)
|
124
141
|
rescue StandardError => e
|
@@ -189,6 +206,19 @@ var console = { history: [] };
|
|
189
206
|
JS
|
190
207
|
# rubocop:enable Layout/IndentHeredoc
|
191
208
|
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
def file_url_to_string(url)
|
213
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
214
|
+
content_type_header = response["content-type"]
|
215
|
+
match = content_type_header.match(/\A.*; charset=(?<encoding>.*)\z/)
|
216
|
+
encoding_type = match[:encoding]
|
217
|
+
response.body.force_encoding(encoding_type)
|
218
|
+
rescue StandardError => e
|
219
|
+
msg = "file_url_to_string #{url} failed\nError is: #{e}"
|
220
|
+
raise ReactOnRails::Error, msg
|
221
|
+
end
|
192
222
|
end
|
193
223
|
end
|
194
224
|
end
|