react_on_rails 16.1.2 → 16.2.0
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/.rspec +2 -0
- data/.rubocop.yml +85 -0
- data/Gemfile.development_dependencies +8 -7
- data/Gemfile.lock +158 -119
- data/Steepfile +56 -0
- data/lib/generators/react_on_rails/base_generator.rb +43 -120
- data/lib/generators/react_on_rails/dev_tests_generator.rb +2 -1
- data/lib/generators/react_on_rails/generator_helper.rb +102 -2
- data/lib/generators/react_on_rails/install_generator.rb +36 -156
- data/lib/generators/react_on_rails/js_dependency_manager.rb +383 -0
- data/lib/generators/react_on_rails/templates/base/base/.dev-services.yml.example +76 -0
- data/lib/generators/react_on_rails/templates/base/base/bin/shakapacker-precompile-hook +30 -0
- data/lib/generators/react_on_rails/templates/base/base/bin/switch-bundler +141 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +44 -45
- data/lib/generators/react_on_rails/templates/base/base/config/{shakapacker.yml → shakapacker.yml.tt} +28 -3
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +15 -9
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +42 -6
- data/lib/react_on_rails/configuration.rb +149 -32
- data/lib/react_on_rails/controller.rb +3 -3
- data/lib/react_on_rails/dev/pack_generator.rb +168 -2
- data/lib/react_on_rails/dev/process_manager.rb +136 -14
- data/lib/react_on_rails/dev/server_manager.rb +194 -26
- data/lib/react_on_rails/dev/service_checker.rb +200 -0
- data/lib/react_on_rails/doctor.rb +341 -12
- data/lib/react_on_rails/engine.rb +75 -1
- data/lib/react_on_rails/git_utils.rb +3 -1
- data/lib/react_on_rails/helper.rb +70 -192
- data/lib/react_on_rails/locales/base.rb +17 -5
- data/lib/react_on_rails/packer_utils.rb +79 -2
- data/lib/react_on_rails/packs_generator.rb +57 -39
- data/lib/react_on_rails/prerender_error.rb +74 -17
- data/lib/react_on_rails/pro_helper.rb +64 -0
- data/lib/react_on_rails/react_component/render_options.rb +7 -7
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +2 -5
- data/lib/react_on_rails/smart_error.rb +326 -0
- data/lib/react_on_rails/system_checker.rb +8 -9
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +16 -7
- data/lib/react_on_rails/utils.rb +241 -55
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +383 -35
- data/lib/tasks/generate_packs.rake +12 -6
- data/lib/tasks/locale.rake +6 -1
- data/rakelib/docker.rake +26 -0
- data/rakelib/dummy_apps.rake +30 -0
- data/rakelib/example_type.rb +121 -0
- data/rakelib/examples_config.yml +52 -0
- data/rakelib/lint.rake +52 -0
- data/rakelib/node_package.rake +15 -0
- data/rakelib/rbs.rake +70 -0
- data/rakelib/run_rspec.rake +223 -0
- data/rakelib/shakapacker_examples.rake +171 -0
- data/rakelib/task_helpers.rb +134 -0
- data/rakelib/update_changelog.rake +73 -0
- data/react_on_rails.gemspec +4 -3
- data/sig/README.md +52 -0
- data/sig/react_on_rails/configuration.rbs +96 -0
- data/sig/react_on_rails/controller.rbs +15 -0
- data/sig/react_on_rails/dev/file_manager.rbs +15 -0
- data/sig/react_on_rails/dev/pack_generator.rbs +19 -0
- data/sig/react_on_rails/dev/process_manager.rbs +22 -0
- data/sig/react_on_rails/dev/server_manager.rbs +39 -0
- data/sig/react_on_rails/dev/service_checker.rbs +22 -0
- data/sig/react_on_rails/error.rbs +4 -0
- data/sig/react_on_rails/generators/js_dependency_manager.rbs +123 -0
- data/sig/react_on_rails/git_utils.rbs +8 -0
- data/sig/react_on_rails/helper.rbs +65 -0
- data/sig/react_on_rails/json_parse_error.rbs +10 -0
- data/sig/react_on_rails/locales.rbs +46 -0
- data/sig/react_on_rails/packer_utils.rbs +15 -0
- data/sig/react_on_rails/prerender_error.rbs +21 -0
- data/sig/react_on_rails/server_rendering_pool.rbs +12 -0
- data/sig/react_on_rails/smart_error.rbs +28 -0
- data/sig/react_on_rails/test_helper.rbs +11 -0
- data/sig/react_on_rails/utils.rbs +34 -0
- data/sig/react_on_rails/version_checker.rbs +12 -0
- data/sig/react_on_rails.rbs +17 -0
- metadata +49 -32
- data/AI_AGENT_INSTRUCTIONS.md +0 -63
- data/CHANGELOG.md +0 -1836
- data/CLAUDE.md +0 -135
- data/CODING_AGENTS.md +0 -313
- data/CONTRIBUTING.md +0 -668
- data/Dockerfile_tests +0 -12
- data/KUDOS.md +0 -114
- data/LICENSE.md +0 -47
- data/LICENSES/README.md +0 -14
- data/NEWS.md +0 -62
- data/PROJECTS.md +0 -63
- data/REACT-ON-RAILS-PRO-LICENSE.md +0 -129
- data/README.md +0 -217
- data/SUMMARY.md +0 -88
- data/TODO.md +0 -135
- data/bin/lefthook/check-trailing-newlines +0 -38
- data/bin/lefthook/get-changed-files +0 -26
- data/bin/lefthook/prettier-format +0 -26
- data/bin/lefthook/ruby-autofix +0 -26
- data/bin/lefthook/ruby-lint +0 -27
- data/docker-compose.yml +0 -11
- data/eslint.config.ts +0 -232
- data/knip.ts +0 -114
- data/lib/react_on_rails/pro/NOTICE +0 -21
- data/lib/react_on_rails/pro/helper.rb +0 -122
- data/lib/react_on_rails/pro/utils.rb +0 -53
- data/tsconfig.eslint.json +0 -6
- data/tsconfig.json +0 -19
data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt
CHANGED
|
@@ -1,51 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# React on Rails configuration
|
|
4
|
+
# See https://github.com/shakacode/react_on_rails/blob/master/docs/configuration/configuration.md
|
|
5
|
+
# for complete documentation of all configuration options.
|
|
5
6
|
|
|
6
7
|
ReactOnRails.configure do |config|
|
|
7
|
-
# This configures the script to run to build the production assets by webpack. Set this to nil
|
|
8
|
-
# if you don't want react_on_rails building this file for you.
|
|
9
|
-
# If nil, then the standard shakacode/shakapacker assets:precompile will run
|
|
10
|
-
# config.build_production_command = nil
|
|
11
|
-
|
|
12
|
-
################################################################################
|
|
13
8
|
################################################################################
|
|
14
|
-
#
|
|
15
|
-
# Below options are used with the use of this test helper:
|
|
16
|
-
# ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
|
|
9
|
+
# Server Rendering (Recommended)
|
|
17
10
|
################################################################################
|
|
11
|
+
# Configure server bundle for server-side rendering with `prerender: true`
|
|
12
|
+
# Set to "" if you're not using server rendering
|
|
13
|
+
config.server_bundle_js_file = "server-bundle.js"
|
|
18
14
|
|
|
19
|
-
#
|
|
15
|
+
# ⚠️ RECOMMENDED: Use Shakapacker 9.0+ private_output_path instead
|
|
20
16
|
#
|
|
21
|
-
#
|
|
17
|
+
# If using Shakapacker 9.0+, add to config/shakapacker.yml:
|
|
18
|
+
# private_output_path: ssr-generated
|
|
22
19
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
20
|
+
# React on Rails will auto-detect this value, eliminating the need to set it here.
|
|
21
|
+
# This keeps your webpack and Rails configs in sync automatically.
|
|
25
22
|
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
config.build_test_command = "RAILS_ENV=test bin/shakapacker"
|
|
29
|
-
|
|
30
|
-
################################################################################
|
|
31
|
-
################################################################################
|
|
32
|
-
# SERVER RENDERING OPTIONS
|
|
33
|
-
################################################################################
|
|
34
|
-
# This is the file used for server rendering of React when using `(prerender: true)`
|
|
35
|
-
# If you are never using server rendering, you should set this to "".
|
|
36
|
-
# Note, there is only one server bundle, unlike JavaScript where you want to minimize the size
|
|
37
|
-
# of the JS sent to the client. For the server rendering, React on Rails creates a pool of
|
|
38
|
-
# JavaScript execution instances which should handle any component requested.
|
|
39
|
-
#
|
|
40
|
-
# While you may configure this to be the same as your client bundle file, this file is typically
|
|
41
|
-
# different. You should have ONE server bundle which can create all of your server rendered
|
|
42
|
-
# React components.
|
|
23
|
+
# For older Shakapacker versions or custom setups, manually configure:
|
|
24
|
+
# config.server_bundle_output_path = "ssr-generated"
|
|
43
25
|
#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# Configure where server bundles are output. Defaults to "ssr-generated".
|
|
47
|
-
# This should match your webpack configuration for server bundles.
|
|
48
|
-
config.server_bundle_output_path = "ssr-generated"
|
|
26
|
+
# The path is relative to Rails.root and should point to a private directory
|
|
27
|
+
# (outside of public/) for security. Run 'rails react_on_rails:doctor' to verify.
|
|
49
28
|
|
|
50
29
|
# Enforce that server bundles are only loaded from private (non-public) directories.
|
|
51
30
|
# When true, server bundles will only be loaded from the configured server_bundle_output_path.
|
|
@@ -53,15 +32,35 @@ ReactOnRails.configure do |config|
|
|
|
53
32
|
config.enforce_private_server_bundles = true
|
|
54
33
|
|
|
55
34
|
################################################################################
|
|
35
|
+
# Test Configuration (Optional)
|
|
56
36
|
################################################################################
|
|
57
|
-
#
|
|
58
|
-
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
|
|
37
|
+
# ⚠️ IMPORTANT: Two mutually exclusive approaches - use ONLY ONE:
|
|
38
|
+
#
|
|
39
|
+
# RECOMMENDED APPROACH: Set `compile: true` in config/shakapacker.yml test section
|
|
40
|
+
# - Simpler configuration (no additional setup needed)
|
|
41
|
+
# - Handled automatically by Shakapacker
|
|
62
42
|
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
43
|
+
# ALTERNATIVE APPROACH: Uncomment below AND configure ReactOnRails::TestHelper
|
|
44
|
+
# - Provides explicit control over test asset compilation timing
|
|
45
|
+
# - Requires adding ReactOnRails::TestHelper to spec/rails_helper.rb
|
|
46
|
+
# - See: https://github.com/shakacode/react_on_rails/blob/master/docs/guides/testing-configuration.md
|
|
47
|
+
#
|
|
48
|
+
config.build_test_command = "RAILS_ENV=test bin/shakapacker"
|
|
49
|
+
|
|
66
50
|
config.auto_load_bundle = true
|
|
51
|
+
config.components_subdirectory = "ror_components"
|
|
52
|
+
################################################################################
|
|
53
|
+
# Advanced Configuration
|
|
54
|
+
################################################################################
|
|
55
|
+
# Most configuration options have sensible defaults and don't need to be set.
|
|
56
|
+
# For advanced options including:
|
|
57
|
+
# - File-based component registry (components_subdirectory, auto_load_bundle)
|
|
58
|
+
# - Component loading strategies (async/defer/sync)
|
|
59
|
+
# - Server bundle security and organization
|
|
60
|
+
# - I18n configuration
|
|
61
|
+
# - Server rendering pool configuration
|
|
62
|
+
# - Custom rendering extensions
|
|
63
|
+
# - And more...
|
|
64
|
+
#
|
|
65
|
+
# See: https://github.com/shakacode/react_on_rails/blob/master/docs/configuration/configuration.md
|
|
67
66
|
end
|
data/lib/generators/react_on_rails/templates/base/base/config/{shakapacker.yml → shakapacker.yml.tt}
RENAMED
|
@@ -29,6 +29,15 @@ default: &default
|
|
|
29
29
|
# Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
|
|
30
30
|
# manifest_path: public/packs/manifest.json
|
|
31
31
|
|
|
32
|
+
# Location for private server-side bundles (e.g., for SSR)
|
|
33
|
+
# These bundles are not served publicly, unlike public_output_path
|
|
34
|
+
# Shakapacker 9.0+ feature - automatically detected by React on Rails
|
|
35
|
+
<% if shakapacker_version_9_or_higher? -%>
|
|
36
|
+
private_output_path: ssr-generated
|
|
37
|
+
<% else -%>
|
|
38
|
+
# private_output_path: ssr-generated # Uncomment to enable (requires Shakapacker 9.0+)
|
|
39
|
+
<% end -%>
|
|
40
|
+
|
|
32
41
|
# Additional paths webpack should look up modules
|
|
33
42
|
# ['app/assets', 'engine/foo/app/assets']
|
|
34
43
|
additional_paths: []
|
|
@@ -36,12 +45,24 @@ default: &default
|
|
|
36
45
|
# Reload manifest.json on all requests so we reload latest compiled packs
|
|
37
46
|
cache_manifest: false
|
|
38
47
|
|
|
39
|
-
# Select
|
|
40
|
-
|
|
48
|
+
# Select JavaScript transpiler to use
|
|
49
|
+
# Available options: 'swc' (default, 20x faster), 'babel', 'esbuild', or 'none'
|
|
50
|
+
# Use 'none' when providing a completely custom webpack configuration
|
|
51
|
+
# Note: When using rspack, swc is used automatically regardless of this setting
|
|
52
|
+
javascript_transpiler: "swc"
|
|
53
|
+
|
|
54
|
+
# Select assets bundler to use
|
|
55
|
+
# Available options: 'webpack' (default) or 'rspack'
|
|
56
|
+
assets_bundler: "webpack"
|
|
41
57
|
|
|
42
58
|
# Raises an error if there is a mismatch in the shakapacker gem and npm package being used
|
|
43
59
|
ensure_consistent_versioning: true
|
|
44
60
|
|
|
61
|
+
# Hook to run before webpack compilation (e.g., for generating dynamic entry points)
|
|
62
|
+
# SECURITY: Only reference trusted scripts within your project. Ensure the hook path
|
|
63
|
+
# points to a file within the project root that you control.
|
|
64
|
+
precompile_hook: 'bin/shakapacker-precompile-hook'
|
|
65
|
+
|
|
45
66
|
# Select whether the compiler will use SHA digest ('digest' option) or most recent modified timestamp ('mtime') to determine freshness
|
|
46
67
|
compiler_strategy: digest
|
|
47
68
|
|
|
@@ -50,6 +71,11 @@ default: &default
|
|
|
50
71
|
# https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
|
|
51
72
|
useContentHash: false
|
|
52
73
|
|
|
74
|
+
# On-demand compilation of packs when modified. Defaults to false.
|
|
75
|
+
# Set to false if using bin/shakapacker-dev-server or bin/shakapacker --watch via Procfiles.
|
|
76
|
+
# Set to true only in test environment for on-demand compilation.
|
|
77
|
+
compile: false
|
|
78
|
+
|
|
53
79
|
# Setting the asset host here will override Rails.application.config.asset_host.
|
|
54
80
|
# Here, you can set different asset_host per environment. Note that
|
|
55
81
|
# SHAKAPACKER_ASSET_HOST will override both configurations.
|
|
@@ -67,7 +93,6 @@ default: &default
|
|
|
67
93
|
|
|
68
94
|
development:
|
|
69
95
|
<<: *default
|
|
70
|
-
compile: true
|
|
71
96
|
compiler_strategy: mtime
|
|
72
97
|
|
|
73
98
|
# Reference: https://webpack.js.org/configuration/dev-server/
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
<%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/development.js") %>
|
|
2
2
|
|
|
3
|
-
const { devServer, inliningCss } = require('shakapacker');
|
|
3
|
+
const { devServer, inliningCss, config } = require('shakapacker');
|
|
4
4
|
|
|
5
5
|
const generateWebpackConfigs = require('./generateWebpackConfigs');
|
|
6
6
|
|
|
7
7
|
const developmentEnvOnly = (clientWebpackConfig, _serverWebpackConfig) => {
|
|
8
|
-
// React Refresh (Fast Refresh) setup - only when
|
|
9
|
-
// This matches the condition in generateWebpackConfigs.js and babel.config.js
|
|
8
|
+
// React Refresh (Fast Refresh) setup - only when dev server is running (HMR mode)
|
|
10
9
|
if (process.env.WEBPACK_SERVE) {
|
|
11
10
|
// eslint-disable-next-line global-require
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
if (config.assets_bundler === 'rspack') {
|
|
12
|
+
// Rspack uses @rspack/plugin-react-refresh for React Fast Refresh
|
|
13
|
+
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');
|
|
14
|
+
clientWebpackConfig.plugins.push(new ReactRefreshPlugin());
|
|
15
|
+
} else {
|
|
16
|
+
// Webpack uses @pmmmwh/react-refresh-webpack-plugin
|
|
17
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
18
|
+
clientWebpackConfig.plugins.push(
|
|
19
|
+
new ReactRefreshWebpackPlugin({
|
|
20
|
+
// Use default overlay configuration for better compatibility
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
}
|
|
18
24
|
}
|
|
19
25
|
};
|
|
20
26
|
|
data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
const { merge, config } = require('shakapacker');
|
|
4
4
|
const commonWebpackConfig = require('./commonWebpackConfig');
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const bundler = config.assets_bundler === 'rspack'
|
|
7
|
+
? require('@rspack/core')
|
|
8
|
+
: require('webpack');
|
|
7
9
|
|
|
8
10
|
const configureServer = () => {
|
|
9
11
|
// We need to use "merge" because the clientConfigObject, EVEN after running
|
|
@@ -40,21 +42,55 @@ const configureServer = () => {
|
|
|
40
42
|
serverWebpackConfig.optimization = {
|
|
41
43
|
minimize: false,
|
|
42
44
|
};
|
|
43
|
-
serverWebpackConfig.plugins.unshift(new
|
|
45
|
+
serverWebpackConfig.plugins.unshift(new bundler.optimize.LimitChunkCountPlugin({ maxChunks: 1 }));
|
|
46
|
+
|
|
47
|
+
// Custom output for the server-bundle
|
|
48
|
+
<% if shakapacker_version_9_or_higher? -%>
|
|
49
|
+
// Using Shakapacker 9.0+ privateOutputPath for automatic sync with shakapacker.yml
|
|
50
|
+
// This eliminates manual path configuration and keeps configs in sync.
|
|
51
|
+
// Falls back to hardcoded path if private_output_path is not configured.
|
|
52
|
+
const serverBundleOutputPath = config.privateOutputPath ||
|
|
53
|
+
require('path').resolve(__dirname, '../../ssr-generated');
|
|
54
|
+
<% else -%>
|
|
55
|
+
// Using hardcoded path (Shakapacker < 9.0)
|
|
56
|
+
// For Shakapacker 9.0+, consider using config.privateOutputPath instead
|
|
57
|
+
// to automatically sync with shakapacker.yml private_output_path.
|
|
58
|
+
const serverBundleOutputPath = require('path').resolve(__dirname, '../../ssr-generated');
|
|
59
|
+
<% end -%>
|
|
44
60
|
|
|
45
|
-
// Custom output for the server-bundle that matches the config in
|
|
46
|
-
// config/initializers/react_on_rails.rb
|
|
47
|
-
// Server bundles are output to a private directory (not public) for security
|
|
48
61
|
serverWebpackConfig.output = {
|
|
49
62
|
filename: 'server-bundle.js',
|
|
50
63
|
globalObject: 'this',
|
|
51
64
|
// If using the React on Rails Pro node server renderer, uncomment the next line
|
|
52
65
|
// libraryTarget: 'commonjs2',
|
|
53
|
-
path:
|
|
66
|
+
path: serverBundleOutputPath,
|
|
54
67
|
// No publicPath needed since server bundles are not served via web
|
|
55
68
|
// https://webpack.js.org/configuration/output/#outputglobalobject
|
|
56
69
|
};
|
|
57
70
|
|
|
71
|
+
// Validate server bundle output path configuration
|
|
72
|
+
<% if shakapacker_version_9_or_higher? -%>
|
|
73
|
+
// For Shakapacker 9.0+, verify privateOutputPath is configured in shakapacker.yml
|
|
74
|
+
if (!config.privateOutputPath) {
|
|
75
|
+
console.warn('⚠️ Shakapacker 9.0+ detected but private_output_path not configured in shakapacker.yml');
|
|
76
|
+
console.warn(' Add to config/shakapacker.yml:');
|
|
77
|
+
console.warn(' private_output_path: ssr-generated');
|
|
78
|
+
console.warn(' Run: rails react_on_rails:doctor to validate your configuration');
|
|
79
|
+
}
|
|
80
|
+
<% else -%>
|
|
81
|
+
// For Shakapacker < 9.0, verify hardcoded path syncs with Rails config
|
|
82
|
+
// 1. Ensure config/initializers/react_on_rails.rb has: config.server_bundle_output_path = "ssr-generated"
|
|
83
|
+
// 2. Run: rails react_on_rails:doctor to verify configuration
|
|
84
|
+
const fs = require('fs');
|
|
85
|
+
if (!fs.existsSync(serverBundleOutputPath)) {
|
|
86
|
+
console.warn(`⚠️ Server bundle output directory does not exist: ${serverBundleOutputPath}`);
|
|
87
|
+
console.warn(' It will be created during build, but ensure React on Rails is configured:');
|
|
88
|
+
console.warn(' config.server_bundle_output_path = "ssr-generated" in config/initializers/react_on_rails.rb');
|
|
89
|
+
console.warn(' Run: rails react_on_rails:doctor to validate your configuration');
|
|
90
|
+
}
|
|
91
|
+
<% end -%>
|
|
92
|
+
|
|
93
|
+
|
|
58
94
|
// Don't hash the server bundle b/c would conflict with the client manifest
|
|
59
95
|
// And no need for the MiniCssExtractPlugin
|
|
60
96
|
serverWebpackConfig.plugins = serverWebpackConfig.plugins.filter(
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
|
4
|
+
require "active_support/core_ext/object/blank"
|
|
5
|
+
|
|
6
|
+
# Polyfill for compact_blank (added in Rails 6.1) to support Rails 5.2-6.0
|
|
7
|
+
unless [].respond_to?(:compact_blank)
|
|
8
|
+
module Enumerable
|
|
9
|
+
def compact_blank
|
|
10
|
+
reject(&:blank?)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Array
|
|
15
|
+
def compact_blank
|
|
16
|
+
reject(&:blank?)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
3
21
|
# rubocop:disable Metrics/ClassLength
|
|
4
22
|
|
|
5
23
|
module ReactOnRails
|
|
@@ -9,9 +27,8 @@ module ReactOnRails
|
|
|
9
27
|
end
|
|
10
28
|
|
|
11
29
|
DEFAULT_GENERATED_ASSETS_DIR = File.join(%w[public webpack], Rails.env).freeze
|
|
12
|
-
DEFAULT_REACT_CLIENT_MANIFEST_FILE = "react-client-manifest.json"
|
|
13
|
-
DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE = "react-server-client-manifest.json"
|
|
14
30
|
DEFAULT_COMPONENT_REGISTRY_TIMEOUT = 5000
|
|
31
|
+
DEFAULT_SERVER_BUNDLE_OUTPUT_PATH = "ssr-generated"
|
|
15
32
|
|
|
16
33
|
def self.configuration
|
|
17
34
|
@configuration ||= Configuration.new(
|
|
@@ -20,9 +37,6 @@ module ReactOnRails
|
|
|
20
37
|
# generated_assets_dirs is deprecated
|
|
21
38
|
generated_assets_dir: "",
|
|
22
39
|
server_bundle_js_file: "",
|
|
23
|
-
rsc_bundle_js_file: "",
|
|
24
|
-
react_client_manifest_file: DEFAULT_REACT_CLIENT_MANIFEST_FILE,
|
|
25
|
-
react_server_client_manifest_file: DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE,
|
|
26
40
|
prerender: false,
|
|
27
41
|
auto_load_bundle: false,
|
|
28
42
|
replay_console: true,
|
|
@@ -46,19 +60,14 @@ module ReactOnRails
|
|
|
46
60
|
components_subdirectory: nil,
|
|
47
61
|
make_generated_server_bundle_the_entrypoint: false,
|
|
48
62
|
defer_generated_component_packs: false,
|
|
49
|
-
# React on Rails Pro (licensed) feature - enables immediate hydration of React components
|
|
50
|
-
immediate_hydration: false,
|
|
51
63
|
# Maximum time in milliseconds to wait for client-side component registration after page load.
|
|
52
64
|
# If exceeded, an error will be thrown for server-side rendered components not registered on the client.
|
|
53
65
|
# Set to 0 to disable the timeout and wait indefinitely for component registration.
|
|
54
66
|
component_registry_timeout: DEFAULT_COMPONENT_REGISTRY_TIMEOUT,
|
|
55
67
|
generated_component_packs_loading_strategy: nil,
|
|
56
|
-
server_bundle_output_path:
|
|
68
|
+
server_bundle_output_path: DEFAULT_SERVER_BUNDLE_OUTPUT_PATH,
|
|
57
69
|
enforce_private_server_bundles: false
|
|
58
70
|
)
|
|
59
|
-
# TODO: Add automatic detection of server_bundle_output_path from shakapacker.yml
|
|
60
|
-
# See feature/shakapacker-yml-integration branch for implementation
|
|
61
|
-
# Requires Shakapacker v8.5.0+ and semantic version checking
|
|
62
71
|
end
|
|
63
72
|
|
|
64
73
|
class Configuration
|
|
@@ -72,10 +81,55 @@ module ReactOnRails
|
|
|
72
81
|
:server_render_method, :random_dom_id, :auto_load_bundle,
|
|
73
82
|
:same_bundle_for_client_and_server, :rendering_props_extension,
|
|
74
83
|
:make_generated_server_bundle_the_entrypoint,
|
|
75
|
-
:generated_component_packs_loading_strategy,
|
|
76
|
-
:
|
|
84
|
+
:generated_component_packs_loading_strategy,
|
|
85
|
+
:component_registry_timeout,
|
|
77
86
|
:server_bundle_output_path, :enforce_private_server_bundles
|
|
78
87
|
|
|
88
|
+
# Class instance variable and mutex to track if deprecation warning has been shown
|
|
89
|
+
# Using mutex to ensure thread-safety in multi-threaded environments
|
|
90
|
+
@immediate_hydration_warned = false
|
|
91
|
+
@immediate_hydration_mutex = Mutex.new
|
|
92
|
+
|
|
93
|
+
class << self
|
|
94
|
+
attr_accessor :immediate_hydration_warned, :immediate_hydration_mutex
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Deprecated: immediate_hydration configuration has been removed
|
|
98
|
+
def immediate_hydration=(value)
|
|
99
|
+
warned = false
|
|
100
|
+
self.class.immediate_hydration_mutex.synchronize do
|
|
101
|
+
warned = self.class.immediate_hydration_warned
|
|
102
|
+
self.class.immediate_hydration_warned = true unless warned
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return if warned
|
|
106
|
+
|
|
107
|
+
Rails.logger.warn <<~WARNING
|
|
108
|
+
[REACT ON RAILS] The 'config.immediate_hydration' configuration option is deprecated and no longer used.
|
|
109
|
+
Immediate hydration is now automatically enabled for React on Rails Pro users.
|
|
110
|
+
Please remove 'config.immediate_hydration = #{value}' from your config/initializers/react_on_rails.rb file.
|
|
111
|
+
See CHANGELOG.md for migration instructions.
|
|
112
|
+
WARNING
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def immediate_hydration
|
|
116
|
+
warned = false
|
|
117
|
+
self.class.immediate_hydration_mutex.synchronize do
|
|
118
|
+
warned = self.class.immediate_hydration_warned
|
|
119
|
+
self.class.immediate_hydration_warned = true unless warned
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
return nil if warned
|
|
123
|
+
|
|
124
|
+
Rails.logger.warn <<~WARNING
|
|
125
|
+
[REACT ON RAILS] The 'config.immediate_hydration' configuration option is deprecated and no longer used.
|
|
126
|
+
Immediate hydration is now automatically enabled for React on Rails Pro users.
|
|
127
|
+
Please remove any references to 'config.immediate_hydration' from your config/initializers/react_on_rails.rb file.
|
|
128
|
+
See CHANGELOG.md for migration instructions.
|
|
129
|
+
WARNING
|
|
130
|
+
nil
|
|
131
|
+
end
|
|
132
|
+
|
|
79
133
|
# rubocop:disable Metrics/AbcSize
|
|
80
134
|
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
|
|
81
135
|
replay_console: nil, make_generated_server_bundle_the_entrypoint: nil,
|
|
@@ -89,8 +143,7 @@ module ReactOnRails
|
|
|
89
143
|
same_bundle_for_client_and_server: nil,
|
|
90
144
|
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil, i18n_yml_safe_load_options: nil,
|
|
91
145
|
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
|
|
92
|
-
components_subdirectory: nil, auto_load_bundle: nil,
|
|
93
|
-
rsc_bundle_js_file: nil, react_client_manifest_file: nil, react_server_client_manifest_file: nil,
|
|
146
|
+
components_subdirectory: nil, auto_load_bundle: nil,
|
|
94
147
|
component_registry_timeout: nil, server_bundle_output_path: nil, enforce_private_server_bundles: nil)
|
|
95
148
|
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
|
|
96
149
|
self.generated_assets_dirs = generated_assets_dirs
|
|
@@ -119,9 +172,6 @@ module ReactOnRails
|
|
|
119
172
|
|
|
120
173
|
# Server rendering:
|
|
121
174
|
self.server_bundle_js_file = server_bundle_js_file
|
|
122
|
-
self.rsc_bundle_js_file = rsc_bundle_js_file
|
|
123
|
-
self.react_client_manifest_file = react_client_manifest_file
|
|
124
|
-
self.react_server_client_manifest_file = react_server_client_manifest_file
|
|
125
175
|
self.same_bundle_for_client_and_server = same_bundle_for_client_and_server
|
|
126
176
|
self.server_renderer_pool_size = self.development_mode ? 1 : server_renderer_pool_size
|
|
127
177
|
self.server_renderer_timeout = server_renderer_timeout # seconds
|
|
@@ -134,7 +184,6 @@ module ReactOnRails
|
|
|
134
184
|
self.auto_load_bundle = auto_load_bundle
|
|
135
185
|
self.make_generated_server_bundle_the_entrypoint = make_generated_server_bundle_the_entrypoint
|
|
136
186
|
self.defer_generated_component_packs = defer_generated_component_packs
|
|
137
|
-
self.immediate_hydration = immediate_hydration
|
|
138
187
|
self.generated_component_packs_loading_strategy = generated_component_packs_loading_strategy
|
|
139
188
|
self.server_bundle_output_path = server_bundle_output_path
|
|
140
189
|
self.enforce_private_server_bundles = enforce_private_server_bundles
|
|
@@ -154,6 +203,7 @@ module ReactOnRails
|
|
|
154
203
|
check_component_registry_timeout
|
|
155
204
|
validate_generated_component_packs_loading_strategy
|
|
156
205
|
validate_enforce_private_server_bundles
|
|
206
|
+
auto_detect_server_bundle_path_from_shakapacker
|
|
157
207
|
end
|
|
158
208
|
|
|
159
209
|
private
|
|
@@ -184,12 +234,13 @@ module ReactOnRails
|
|
|
184
234
|
|
|
185
235
|
msg = <<~MSG
|
|
186
236
|
ReactOnRails: Your current version of shakapacker \
|
|
187
|
-
does not support async script loading
|
|
188
|
-
1. Use :
|
|
237
|
+
does not support async script loading. Please either:
|
|
238
|
+
1. Use :defer or :sync loading strategy instead of :async
|
|
189
239
|
2. Upgrade to Shakapacker v8.2.0 or above to enable async script loading
|
|
190
240
|
MSG
|
|
191
241
|
if PackerUtils.supports_async_loading?
|
|
192
|
-
|
|
242
|
+
# Default based on Pro license: Pro users get :async, non-Pro users get :defer
|
|
243
|
+
self.generated_component_packs_loading_strategy ||= (Utils.react_on_rails_pro? ? :async : :defer)
|
|
193
244
|
elsif generated_component_packs_loading_strategy.nil?
|
|
194
245
|
Rails.logger.warn("**WARNING** #{msg}")
|
|
195
246
|
self.generated_component_packs_loading_strategy = :sync
|
|
@@ -226,6 +277,57 @@ module ReactOnRails
|
|
|
226
277
|
"the public directory. Please set it to a directory outside of public."
|
|
227
278
|
end
|
|
228
279
|
|
|
280
|
+
# Auto-detect server_bundle_output_path from Shakapacker 9.0+ private_output_path
|
|
281
|
+
# Checks if user explicitly set a value and warns them to use auto-detection instead
|
|
282
|
+
def auto_detect_server_bundle_path_from_shakapacker
|
|
283
|
+
# Skip if Shakapacker is not available
|
|
284
|
+
return unless defined?(::Shakapacker)
|
|
285
|
+
|
|
286
|
+
# Check if Shakapacker config has private_output_path method (9.0+)
|
|
287
|
+
return unless ::Shakapacker.config.respond_to?(:private_output_path)
|
|
288
|
+
|
|
289
|
+
# Get the private_output_path from Shakapacker
|
|
290
|
+
private_path = ::Shakapacker.config.private_output_path
|
|
291
|
+
return unless private_path
|
|
292
|
+
|
|
293
|
+
relative_path = ReactOnRails::Utils.normalize_to_relative_path(private_path)
|
|
294
|
+
|
|
295
|
+
# Check if user explicitly configured server_bundle_output_path
|
|
296
|
+
if server_bundle_output_path != ReactOnRails::DEFAULT_SERVER_BUNDLE_OUTPUT_PATH
|
|
297
|
+
warn_about_explicit_configuration(relative_path)
|
|
298
|
+
return
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
apply_shakapacker_private_output_path(relative_path)
|
|
302
|
+
rescue StandardError => e
|
|
303
|
+
# Fail gracefully - if auto-detection fails, keep the default
|
|
304
|
+
Rails.logger&.debug("ReactOnRails: Could not auto-detect server bundle path from " \
|
|
305
|
+
"Shakapacker: #{e.message}")
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def warn_about_explicit_configuration(shakapacker_path)
|
|
309
|
+
# Normalize both paths for comparison
|
|
310
|
+
normalized_config = server_bundle_output_path.to_s.chomp("/")
|
|
311
|
+
normalized_shakapacker = shakapacker_path.to_s.chomp("/")
|
|
312
|
+
|
|
313
|
+
# Only warn if there's a mismatch
|
|
314
|
+
return if normalized_config == normalized_shakapacker
|
|
315
|
+
|
|
316
|
+
Rails.logger&.warn(
|
|
317
|
+
"ReactOnRails: server_bundle_output_path is explicitly set to '#{server_bundle_output_path}' " \
|
|
318
|
+
"but shakapacker.yml private_output_path is '#{shakapacker_path}'. " \
|
|
319
|
+
"Consider removing server_bundle_output_path from your React on Rails initializer " \
|
|
320
|
+
"to use the auto-detected value from shakapacker.yml."
|
|
321
|
+
)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def apply_shakapacker_private_output_path(relative_path)
|
|
325
|
+
self.server_bundle_output_path = relative_path
|
|
326
|
+
|
|
327
|
+
Rails.logger&.debug("ReactOnRails: Auto-detected server_bundle_output_path from " \
|
|
328
|
+
"shakapacker.yml private_output_path: '#{relative_path}'")
|
|
329
|
+
end
|
|
330
|
+
|
|
229
331
|
def check_minimum_shakapacker_version
|
|
230
332
|
ReactOnRails::PackerUtils.raise_shakapacker_version_incompatible_for_basic_pack_generation unless
|
|
231
333
|
ReactOnRails::PackerUtils.supports_basic_pack_generation?
|
|
@@ -247,7 +349,14 @@ module ReactOnRails
|
|
|
247
349
|
raise(ReactOnRails::Error, compile_command_conflict_message) if ReactOnRails::PackerUtils.precompile?
|
|
248
350
|
|
|
249
351
|
precompile_tasks = lambda {
|
|
250
|
-
|
|
352
|
+
# Skip generate_packs if shakapacker has a precompile hook configured
|
|
353
|
+
if ReactOnRails::PackerUtils.shakapacker_precompile_hook_configured?
|
|
354
|
+
hook_value = ReactOnRails::PackerUtils.shakapacker_precompile_hook_value
|
|
355
|
+
puts "Skipping react_on_rails:generate_packs (configured in shakapacker precompile hook: #{hook_value})"
|
|
356
|
+
else
|
|
357
|
+
Rake::Task["react_on_rails:generate_packs"].invoke
|
|
358
|
+
end
|
|
359
|
+
|
|
251
360
|
Rake::Task["react_on_rails:assets:webpack"].invoke
|
|
252
361
|
|
|
253
362
|
# VERSIONS is per the shakacode/shakapacker clean method definition.
|
|
@@ -320,15 +429,23 @@ module ReactOnRails
|
|
|
320
429
|
end
|
|
321
430
|
|
|
322
431
|
def ensure_webpack_generated_files_exists
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
432
|
+
all_required_files = ["manifest.json", server_bundle_js_file]
|
|
433
|
+
|
|
434
|
+
if ReactOnRails::Utils.react_on_rails_pro?
|
|
435
|
+
pro_config = ReactOnRailsPro.configuration
|
|
436
|
+
all_required_files << pro_config.rsc_bundle_js_file
|
|
437
|
+
all_required_files << pro_config.react_client_manifest_file
|
|
438
|
+
all_required_files << pro_config.react_server_client_manifest_file
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
all_required_files = all_required_files.compact_blank
|
|
442
|
+
|
|
443
|
+
if webpack_generated_files.empty?
|
|
444
|
+
self.webpack_generated_files = all_required_files
|
|
445
|
+
else
|
|
446
|
+
missing_files = all_required_files.reject { |file| webpack_generated_files.include?(file) }
|
|
447
|
+
self.webpack_generated_files += missing_files if missing_files.any?
|
|
448
|
+
end
|
|
332
449
|
end
|
|
333
450
|
|
|
334
451
|
def configure_skip_display_none_deprecation
|
|
@@ -9,13 +9,13 @@ module ReactOnRails
|
|
|
9
9
|
# JavaScript code.
|
|
10
10
|
# props: Named parameter props which is a Ruby Hash or JSON string which contains the properties
|
|
11
11
|
# to pass to the redux store.
|
|
12
|
-
# immediate_hydration: React on Rails Pro (licensed) feature.
|
|
13
|
-
#
|
|
12
|
+
# immediate_hydration: React on Rails Pro (licensed) feature. When nil (default), Pro users get
|
|
13
|
+
# immediate hydration, non-Pro users don't. Can be explicitly overridden.
|
|
14
14
|
#
|
|
15
15
|
# Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view
|
|
16
16
|
# or else there will be no client side hydration of your stores.
|
|
17
17
|
def redux_store(store_name, props: {}, immediate_hydration: nil)
|
|
18
|
-
immediate_hydration = ReactOnRails.
|
|
18
|
+
immediate_hydration = ReactOnRails::Utils.normalize_immediate_hydration(immediate_hydration, store_name, "Store")
|
|
19
19
|
redux_store_data = { store_name: store_name,
|
|
20
20
|
props: props,
|
|
21
21
|
immediate_hydration: immediate_hydration }
|