react_on_rails 11.3.0 → 12.0.0.pre.beta.4
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 +4 -4
- data/.circleci/config.yml +320 -0
- data/.eslintignore +2 -1
- data/.eslintrc +23 -1
- data/.github/FUNDING.yml +1 -0
- data/.gitignore +3 -1
- data/.prettierignore +10 -1
- data/.prettierrc +3 -0
- data/.rubocop.yml +37 -11
- data/.travis.yml +9 -22
- data/CHANGELOG.md +65 -6
- data/CONTRIBUTING.md +60 -71
- data/Gemfile +3 -4
- data/{COMM-LICENSE → REACT-ON-RAILS-PRO-LICENSE} +6 -9
- data/README.md +129 -92
- data/Rakefile +0 -7
- data/SUMMARY.md +7 -11
- data/book.json +5 -5
- data/docs/additional-reading/asset-pipeline.md +8 -16
- data/docs/additional-reading/react-helmet.md +30 -10
- data/docs/additional-reading/react-router.md +52 -75
- data/docs/additional-reading/server-rendering-tips.md +12 -7
- data/docs/api/javascript-api.md +3 -3
- data/docs/api/redux-store-api.md +4 -2
- data/docs/api/view-helpers-api.md +6 -7
- data/docs/basics/configuration.md +83 -69
- data/docs/basics/deployment.md +2 -4
- data/docs/basics/heroku-deployment.md +24 -0
- data/docs/basics/hmr-and-hot-reloading-with-the-webpack-dev-server.md +49 -0
- data/docs/basics/i18n.md +45 -23
- data/docs/basics/installation-into-an-existing-rails-app.md +4 -9
- data/docs/basics/react-server-rendering.md +1 -1
- data/docs/basics/recommended-project-structure.md +5 -22
- data/docs/basics/{generator-functions-and-railscontext.md → render-functions-and-railscontext.md} +59 -21
- data/docs/basics/rspec-configuration.md +27 -16
- data/docs/basics/upgrading-react-on-rails.md +58 -2
- data/docs/basics/webpack-configuration.md +18 -8
- data/docs/contributor-info/errors-with-hooks.md +45 -0
- data/docs/contributor-info/pull-requests.md +44 -0
- data/docs/misc/doctrine.md +1 -1
- data/docs/{misc-pending → outdated}/code-splitting.md +12 -8
- data/docs/{basics → outdated}/how-react-on-rails-works.md +8 -4
- data/docs/{misc-pending → outdated}/manual-installation-overview.md +5 -5
- data/docs/{additional-reading → outdated}/rails-assets-relative-paths.md +3 -3
- data/docs/{misc-pending → outdated}/rails-assets.md +2 -12
- data/docs/{misc → outdated}/rails3.md +0 -0
- data/docs/tutorial.md +94 -68
- data/jest.config.js +4 -0
- data/lib/generators/react_on_rails/base_generator.rb +2 -2
- data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -1
- data/lib/generators/react_on_rails/generator_helper.rb +4 -6
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +3 -1
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +26 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +20 -40
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +4 -1
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +4 -8
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.js +1 -3
- data/lib/react_on_rails.rb +3 -1
- data/lib/react_on_rails/configuration.rb +58 -28
- data/lib/react_on_rails/error.rb +2 -0
- data/lib/react_on_rails/helper.rb +41 -91
- data/lib/react_on_rails/json_parse_error.rb +2 -0
- data/lib/react_on_rails/locales/base.rb +150 -0
- data/lib/react_on_rails/locales/to_js.rb +37 -0
- data/lib/react_on_rails/locales/to_json.rb +27 -0
- data/lib/react_on_rails/prerender_error.rb +11 -15
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +41 -46
- data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +7 -8
- data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +17 -0
- data/lib/react_on_rails/utils.rb +14 -19
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +1 -0
- data/lib/react_on_rails/webpacker_utils.rb +19 -2
- data/lib/tasks/assets.rake +33 -46
- data/lib/tasks/locale.rake +4 -2
- data/package-scripts.yml +11 -8
- data/package.json +29 -28
- data/rakelib/dummy_apps.rake +1 -9
- data/rakelib/example_type.rb +3 -1
- data/rakelib/examples.rake +3 -0
- data/rakelib/lint.rake +2 -7
- data/rakelib/node_package.rake +2 -2
- data/rakelib/release.rake +0 -6
- data/rakelib/run_rspec.rake +5 -18
- data/react_on_rails.gemspec +4 -5
- data/tsconfig.json +14 -0
- data/webpackConfigLoader.js +3 -2
- data/yarn.lock +4333 -2209
- metadata +46 -57
- data/Gemfile.rails32 +0 -73
- data/docs/additional-reading/babel.md +0 -5
- data/docs/additional-reading/heroku-deployment.md +0 -92
- data/docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md +0 -47
- data/docs/api/ruby-api-hot-reload-view-helpers.md +0 -44
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-server +0 -12
- data/lib/react_on_rails/assets_precompile.rb +0 -153
- 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
|