react_on_rails 11.2.2 → 12.0.0.pre.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +320 -0
  3. data/.eslintignore +2 -1
  4. data/.eslintrc +23 -1
  5. data/.github/FUNDING.yml +1 -0
  6. data/.gitignore +3 -1
  7. data/.prettierignore +10 -1
  8. data/.prettierrc +3 -0
  9. data/.rubocop.yml +37 -11
  10. data/.travis.yml +9 -20
  11. data/CHANGELOG.md +73 -6
  12. data/CONTRIBUTING.md +60 -71
  13. data/Gemfile +3 -4
  14. data/{COMM-LICENSE → REACT-ON-RAILS-PRO-LICENSE} +6 -9
  15. data/README.md +137 -95
  16. data/Rakefile +0 -7
  17. data/SUMMARY.md +9 -12
  18. data/book.json +5 -5
  19. data/docs/additional-reading/asset-pipeline.md +8 -16
  20. data/docs/additional-reading/react-helmet.md +30 -10
  21. data/docs/additional-reading/react-router.md +52 -75
  22. data/docs/additional-reading/server-rendering-tips.md +12 -7
  23. data/docs/api/javascript-api.md +3 -3
  24. data/docs/api/redux-store-api.md +4 -2
  25. data/docs/api/view-helpers-api.md +7 -8
  26. data/docs/basics/configuration.md +83 -69
  27. data/docs/basics/deployment.md +2 -4
  28. data/docs/basics/heroku-deployment.md +24 -0
  29. data/docs/basics/hmr-and-hot-reloading-with-the-webpack-dev-server.md +49 -0
  30. data/docs/basics/i18n.md +45 -23
  31. data/docs/basics/installation-into-an-existing-rails-app.md +4 -9
  32. data/docs/basics/minitest-configuration.md +31 -0
  33. data/docs/basics/react-server-rendering.md +1 -1
  34. data/docs/basics/recommended-project-structure.md +5 -22
  35. data/docs/basics/{generator-functions-and-railscontext.md → render-functions-and-railscontext.md} +59 -21
  36. data/docs/basics/rspec-configuration.md +29 -18
  37. data/docs/basics/upgrading-react-on-rails.md +69 -3
  38. data/docs/basics/webpack-configuration.md +18 -8
  39. data/docs/contributor-info/errors-with-hooks.md +45 -0
  40. data/docs/contributor-info/pull-requests.md +44 -0
  41. data/docs/misc/doctrine.md +1 -1
  42. data/docs/{misc-pending → outdated}/code-splitting.md +12 -8
  43. data/docs/{basics → outdated}/how-react-on-rails-works.md +8 -4
  44. data/docs/{misc-pending → outdated}/manual-installation-overview.md +5 -5
  45. data/docs/{additional-reading → outdated}/rails-assets-relative-paths.md +3 -3
  46. data/docs/{misc-pending → outdated}/rails-assets.md +2 -12
  47. data/docs/{misc → outdated}/rails3.md +0 -0
  48. data/docs/testimonials/testimonials.md +3 -3
  49. data/docs/tutorial.md +96 -70
  50. data/jest.config.js +4 -0
  51. data/lib/generators/react_on_rails/base_generator.rb +2 -2
  52. data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -1
  53. data/lib/generators/react_on_rails/generator_helper.rb +4 -6
  54. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +3 -1
  55. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +26 -0
  56. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +20 -40
  57. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +4 -1
  58. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +4 -8
  59. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.js +1 -3
  60. data/lib/react_on_rails.rb +3 -1
  61. data/lib/react_on_rails/configuration.rb +58 -28
  62. data/lib/react_on_rails/error.rb +2 -0
  63. data/lib/react_on_rails/helper.rb +48 -92
  64. data/lib/react_on_rails/json_parse_error.rb +2 -0
  65. data/lib/react_on_rails/locales/base.rb +150 -0
  66. data/lib/react_on_rails/locales/to_js.rb +37 -0
  67. data/lib/react_on_rails/locales/to_json.rb +27 -0
  68. data/lib/react_on_rails/prerender_error.rb +11 -15
  69. data/lib/react_on_rails/react_component/render_options.rb +4 -0
  70. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +41 -46
  71. data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +7 -8
  72. data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +17 -0
  73. data/lib/react_on_rails/utils.rb +14 -19
  74. data/lib/react_on_rails/version.rb +1 -1
  75. data/lib/react_on_rails/version_checker.rb +1 -0
  76. data/lib/react_on_rails/webpacker_utils.rb +19 -2
  77. data/lib/tasks/assets.rake +29 -47
  78. data/lib/tasks/locale.rake +4 -2
  79. data/package-scripts.yml +11 -8
  80. data/package.json +29 -28
  81. data/rakelib/dummy_apps.rake +1 -9
  82. data/rakelib/example_type.rb +3 -1
  83. data/rakelib/examples.rake +3 -0
  84. data/rakelib/lint.rake +2 -7
  85. data/rakelib/node_package.rake +2 -2
  86. data/rakelib/release.rake +0 -6
  87. data/rakelib/run_rspec.rake +5 -18
  88. data/react_on_rails.gemspec +4 -5
  89. data/tsconfig.json +14 -0
  90. data/webpackConfigLoader.js +3 -2
  91. data/yarn.lock +4333 -2209
  92. metadata +47 -57
  93. data/Gemfile.rails32 +0 -73
  94. data/docs/additional-reading/babel.md +0 -5
  95. data/docs/additional-reading/heroku-deployment.md +0 -92
  96. data/docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md +0 -47
  97. data/docs/api/ruby-api-hot-reload-view-helpers.md +0 -44
  98. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-server +0 -12
  99. data/lib/react_on_rails/assets_precompile.rb +0 -153
  100. data/lib/react_on_rails/locales_to_js.rb +0 -138
@@ -1,44 +0,0 @@
1
- ## NOTE: These helpers are NOT needed if using webpacker
2
-
3
- ## Hot Reloading View Helpers
4
- The `env_javascript_include_tag` and `env_stylesheet_link_tag` support the usage of a webpack dev server for providing the JS and CSS assets during development mode. See the [shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/) for a working example.
5
-
6
- The key options are `static` and `hot` which specify what you want for static vs. hot. Both of these params are optional, and support either a single value, or an array.
7
-
8
- static vs. hot is picked based on whether `ENV["REACT_ON_RAILS_ENV"] == "HOT"`
9
-
10
- ```erb
11
- <%= env_stylesheet_link_tag(static: 'application_static',
12
- hot: 'application_non_webpack',
13
- media: 'all',
14
- 'data-turbolinks-track' => true) %>
15
-
16
- <!-- These do not use turbolinks, so no data-turbolinks-track -->
17
- <!-- This is to load the hot assets. -->
18
-
19
- <!-- Note, you can have multiple files here. It's an array. -->
20
- <%= env_javascript_include_tag(hot: ['http://localhost:3500/hello-world-bundle.js]') %>
21
-
22
- <!-- These do use turbolinks -->
23
- <%= env_javascript_include_tag(static: 'application_static',
24
- hot: 'application_non_webpack',
25
- 'data-turbolinks-track' => true) %>
26
- ```
27
-
28
- See application.html.erb for usage example and [application.html.erb](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app%2Fviews%2Flayouts%2Fapplication.html.erb)
29
-
30
- Helper to set CSS and JS assets depending on if we want static or "hot", which means from the Webpack dev server.
31
-
32
- In this example, `application_non_webpack` is simply a CSS asset pipeline file which includes styles not placed in the webpack build. The same can be said for `application_non_webpack` for JS files. Note, the suffix is not used in the helper calls.
33
-
34
- We don't need styles from the webpack build, as those will come via the JavaScript include tags.
35
-
36
- The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
37
- these params are optional, and support either a single value, or an array.
38
-
39
- ```erb
40
- <%= env_stylesheet_link_tag(static: 'application_static',
41
- hot: 'application_non_webpack',
42
- media: 'all',
43
- 'data-turbolinks-track' => true) %>
44
- ```
@@ -1,12 +0,0 @@
1
- # You can run these commands in separate shells instead of using foreman
2
- web: rails s -p 3000
3
-
4
- # Next line runs the webpack-dev-server
5
- # You can edit config/webpacker.yml to set HMR to true to see hot reloading.
6
- # Note, hot and live reloading don't work with the default generator setup on top of
7
- # the rails/webpacker Webpack config with server rendering.
8
- # If you have server rendering enabled, modify the call to bin/webpack-dev-server line
9
- # so you add `--inline=false` and then CSS is not inlined.
10
- # Otherwise, you will have an error. If you want HMR and Server Rendering, see
11
- # the example in the https://github.com/shakacode/react-webpack-rails-tutorial
12
- client: sh -c 'rm -rf public/packs/* || true && bundle exec rake react_on_rails:locale && bin/webpack-dev-server'
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ReactOnRails
4
- class AssetsPrecompile
5
- class SymlinkTargetDoesNotExistException < StandardError
6
- end
7
-
8
- # Used by the rake task
9
- def default_asset_path
10
- dir = File.join(Rails.configuration.paths["public"].first,
11
- Rails.configuration.assets.prefix)
12
- Pathname.new(dir)
13
- end
14
-
15
- # assets_path should be a Pathname object
16
- def initialize(assets_path: nil,
17
- symlink_non_digested_assets_regex: nil,
18
- generated_assets_dir: nil)
19
- @assets_path = ReactOnRails::Utils.truthy_presence(assets_path) || default_asset_path
20
- @symlink_non_digested_assets_regex =
21
- ReactOnRails::Utils.truthy_presence(symlink_non_digested_assets_regex) ||
22
- ReactOnRails.configuration.symlink_non_digested_assets_regex
23
- @generated_assets_dir = ReactOnRails::Utils.truthy_presence(generated_assets_dir) ||
24
- ReactOnRails.configuration.generated_assets_dir
25
- end
26
-
27
- # target and symlink are relative to the assets directory
28
- def symlink_file(target, symlink)
29
- target_path = @assets_path.join(target)
30
- symlink_path = @assets_path.join(symlink)
31
-
32
- target_exists = File.exist?(target_path)
33
- raise SymlinkTargetDoesNotExistException, "Target Path was: #{target_path}" unless target_exists
34
-
35
- if symlink_and_points_to_existing_file?(symlink_path)
36
- puts "React On Rails: Digested version of #{symlink} already exists indicating #{target} did not change."
37
- return
38
- end
39
-
40
- if file_or_symlink_exists_at_path?(symlink_path)
41
- puts "React On Rails: Removing existing invalid symlink or file #{symlink_path}"
42
- FileUtils.remove_file(symlink_path, true)
43
- end
44
-
45
- # Might be like:
46
- # "images/5cf5db49df178f9357603f945752a1ef.png":
47
- # "images/5cf5db49df178f9357603f945752a1ef-033650e1d6193b70d59bb60e773f47b6d9aefdd56abc7cc.png"
48
- # need to cd to directory and then symlink
49
- target_sub_path, _divider, target_filename = target.rpartition("/")
50
- _symlink_sub_path, _divider, symlink_filename = symlink.rpartition("/")
51
- dest_path = File.join(@assets_path, target_sub_path)
52
-
53
- puts "React On Rails: Symlinking \"#{target}\" to \"#{symlink}\""
54
- FileUtils.chdir(dest_path) do
55
- File.symlink(target_filename, symlink_filename)
56
- end
57
- end
58
-
59
- def symlink_non_digested_assets
60
- # digest ==> means that the file has a unique sha so the browser will load a new copy.
61
- # Webpack's CSS extract-text-plugin copies digested asset files over to directory where we put
62
- # we deploy the webpack compiled JS file. Since Rails will deploy the image files in this
63
- # directory with a digest, then the files are essentially "double-digested" and the CSS
64
- # references from webpack's CSS would be invalid. The fix is to symlink the double-digested
65
- # file back to the original digested name, and make a similar symlink for the gz version.
66
- return unless @symlink_non_digested_assets_regex
67
-
68
- manifest_glob = Dir.glob(@assets_path.join(".sprockets-manifest-*.json")) +
69
- Dir.glob(@assets_path.join("manifest-*.json")) +
70
- Dir.glob(@assets_path.join("manifest.yml"))
71
- if manifest_glob.empty?
72
- puts "Warning: React On Rails: expected to find .sprockets-manifest-*.json, manifest-*.json "\
73
- "or manifest.yml at #{@assets_path}, but found none. Canceling symlinking tasks."
74
- return -1
75
- end
76
- manifest_path = take_most_recent_manifest_path(manifest_glob)
77
- manifest_file = File.new(manifest_path)
78
- manifest_data = if File.extname(manifest_file) == ".json"
79
- manifest_file_data = File.read(manifest_path)
80
- JSON.parse(manifest_file_data)["assets"]
81
- else
82
- YAML.safe_load(manifest_file)
83
- end
84
-
85
- # We realize that we're copying other Rails assets that match the regexp, but this just
86
- # means that we'd be exposing the original, undigested names.
87
- manifest_data.each do |original_filename, rails_digested_filename|
88
- # TODO: we should remove any original_filename that is NOT in the webpack deploy folder.
89
- next unless original_filename =~ @symlink_non_digested_assets_regex
90
-
91
- # We're symlinking from the digested filename back to the original filename which has
92
- # already been symlinked by Webpack
93
- symlink_file(rails_digested_filename, original_filename)
94
-
95
- # We want the gz ones as well if they exist
96
- if File.exist?(@assets_path.join("#{rails_digested_filename}.gz"))
97
- symlink_file("#{rails_digested_filename}.gz", "#{original_filename}.gz")
98
- end
99
- end
100
- end
101
-
102
- def delete_broken_symlinks
103
- Dir.glob(@assets_path.join("*")).each do |filename|
104
- next unless File.lstat(filename).symlink?
105
-
106
- begin
107
- target = File.readlink(filename)
108
- rescue StandardError
109
- puts "React on Rails: Warning: your platform doesn't support File::readlink method." \
110
- "Skipping broken link check."
111
- break
112
- end
113
- path = Pathname.new(File.dirname(filename))
114
- target_path = path.join(target)
115
- unless File.exist?(target_path)
116
- puts "React on Rails: Deleting broken link: #{filename}"
117
- File.delete(filename)
118
- end
119
- end
120
- end
121
-
122
- def clobber
123
- dir = Rails.root.join(@generated_assets_dir)
124
- if dir.present? && File.directory?(dir)
125
- puts "Deleting files in directory #{dir}"
126
- FileUtils.rm_r(Dir.glob(Rails.root.join("#{@generated_assets_dir}/*")))
127
- else
128
- puts "Could not find generated_assets_dir #{dir} defined in react_on_rails initializer: "
129
- end
130
- end
131
-
132
- private
133
-
134
- def take_most_recent_manifest_path(manifest_glob)
135
- manifest_glob.max_by { |name| File.mtime(name) }
136
- end
137
-
138
- def symlink_and_points_to_existing_file?(symlink_path)
139
- # File.exist?(symlink_path) will check the file the sym is pointing to is existing
140
- # File.lstat(symlink_path).symlink? confirms that this is a symlink
141
- File.exist?(symlink_path) && File.lstat(symlink_path).symlink?
142
- end
143
-
144
- def file_or_symlink_exists_at_path?(path)
145
- # We use lstat and not stat, we we don't want to visit the file that the symlink maybe
146
- # pointing to. We can't use File.exist?, as that would check the file pointed at by the symlink.
147
- File.lstat(path)
148
- true
149
- rescue StandardError
150
- false
151
- end
152
- end
153
- end
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "erb"
4
-
5
- module ReactOnRails
6
- class LocalesToJs
7
- def initialize
8
- return if i18n_dir.nil?
9
- return unless obsolete?
10
-
11
- @translations, @defaults = generate_translations
12
- convert
13
- end
14
-
15
- private
16
-
17
- def obsolete?
18
- return true if exist_js_files.empty?
19
-
20
- js_files_are_outdated
21
- end
22
-
23
- def exist_js_files
24
- @exist_js_files ||= js_files.select(&File.method(:exist?))
25
- end
26
-
27
- def js_files_are_outdated
28
- latest_yml = locale_files.map(&File.method(:mtime)).max
29
- earliest_js = exist_js_files.map(&File.method(:mtime)).min
30
- latest_yml > earliest_js
31
- end
32
-
33
- def js_file_names
34
- %w[translations default]
35
- end
36
-
37
- def js_files
38
- @js_files ||= js_file_names.map { |n| js_file(n) }
39
- end
40
-
41
- def js_file(name)
42
- "#{i18n_dir}/#{name}.js"
43
- end
44
-
45
- def locale_files
46
- @locale_files ||= begin
47
- if i18n_yml_dir.present?
48
- Dir["#{i18n_yml_dir}/**/*.yml"]
49
- else
50
- ReactOnRails::Utils.truthy_presence(
51
- Rails.application && Rails.application.config.i18n.load_path
52
- ).presence
53
- end
54
- end
55
- end
56
-
57
- def i18n_dir
58
- @i18n_dir ||= ReactOnRails.configuration.i18n_dir
59
- end
60
-
61
- def i18n_yml_dir
62
- @i18n_yml_dir ||= ReactOnRails.configuration.i18n_yml_dir
63
- end
64
-
65
- def default_locale
66
- @default_locale ||= I18n.default_locale.to_s || "en"
67
- end
68
-
69
- def convert
70
- js_file_names.each do |name|
71
- template = send("template_#{name}")
72
- path = js_file(name)
73
- generate_js_file(template, path)
74
- end
75
- end
76
-
77
- def generate_js_file(template, path)
78
- result = ERB.new(template).result()
79
- File.open(path, "w") do |f|
80
- f.write(result)
81
- end
82
- end
83
-
84
- def generate_translations
85
- translations = {}
86
- defaults = {}
87
- locale_files.each do |f|
88
- translation = YAML.safe_load(File.open(f))
89
- key = translation.keys[0]
90
- val = flatten(translation[key])
91
- translations = translations.deep_merge(key => val)
92
- defaults = defaults.deep_merge(flatten_defaults(val)) if key == default_locale
93
- end
94
- [translations.to_json, defaults.to_json]
95
- end
96
-
97
- def format(input)
98
- input.to_s.tr(".", "_").camelize(:lower).to_sym
99
- end
100
-
101
- def flatten_defaults(val)
102
- flatten(val).each_with_object({}) do |(k, v), h|
103
- key = format(k)
104
- h[key] = { id: k, defaultMessage: v }
105
- end
106
- end
107
-
108
- def flatten(translations)
109
- translations.each_with_object({}) do |(k, v), h|
110
- if v.is_a? Hash
111
- flatten(v).map { |hk, hv| h["#{k}.#{hk}".to_sym] = hv }
112
- elsif v.is_a?(String)
113
- h[k] = v.gsub("%{", "{")
114
- elsif !v.is_a?(Array)
115
- h[k] = v
116
- end
117
- end
118
- end
119
-
120
- def template_translations
121
- <<-JS.strip_heredoc
122
- export const translations = #{@translations};
123
- JS
124
- end
125
-
126
- def template_default
127
- <<-JS.strip_heredoc
128
- import { defineMessages } from 'react-intl';
129
-
130
- const defaultLocale = \'#{default_locale}\';
131
-
132
- const defaultMessages = defineMessages(#{@defaults});
133
-
134
- export { defaultMessages, defaultLocale };
135
- JS
136
- end
137
- end
138
- end