diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e6155a915..632ef9621f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ Changes since the last non-beta release. #### Fixed - Fixed a bug where the `load` event was not firing in Safari by postponing hydration to the next JavaScript task using `setTimeout(callback, 0)`. [PR 1729](https://github.com/shakacode/react_on_rails/pull/1729) by [Romex91](https://github.com/Romex91). +- Generated client packs now import from `react-on-rails/client` instead of `react-on-rails`. [PR 1706](https://github.com/shakacode/react_on_rails/pull/1706) by [alexeyr-ci](https://github.com/alexeyr-ci). + - The "optimization opportunity" message when importing the server-side `react-on-rails` instead of `react-on-rails/client` in browsers is now a warning for two reasons: + - Make it more prominent + - Include a stack trace when clicked ### [14.2.0] - 2025-03-03 diff --git a/Gemfile.lock b/Gemfile.lock index 85315a3126..f26f4062bf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - react_on_rails (14.1.1) + react_on_rails (14.2.1) addressable connection_pool execjs (~> 2.5) diff --git a/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md b/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md index 0e318c1c65..1ddb9fdd77 100644 --- a/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md +++ b/docs/guides/how-to-use-different-files-for-client-and-server-rendering.md @@ -8,7 +8,7 @@ Many projects will have different entry points for client and server rendering. Your Client Entry can look like this: ```js -import ReactOnRails from 'react-on-rails'; +import ReactOnRails from 'react-on-rails/client'; import App from './ClientApp'; ReactOnRails.register({ App }) ``` @@ -21,7 +21,7 @@ import App from './ServerApp'; ReactOnRails.register({ App }) ``` -Note that the only difference is on the second line of each of these examples. +Note that the only difference is in the imports. ## B. Two Options for Using Webpack Resolve Alias in the Webpack Config Per [Webpack Docs](https://webpack.js.org/configuration/resolve/#resolve-alias). diff --git a/docs/javascript/code-splitting.md b/docs/javascript/code-splitting.md index 8eb2733f23..5b259b9642 100644 --- a/docs/javascript/code-splitting.md +++ b/docs/javascript/code-splitting.md @@ -37,7 +37,7 @@ Here's an example of how you might use this in practice: #### clientRegistration.js ```js -import ReactOnRails from 'node_package/lib/ReactOnRails'; +import ReactOnRails from 'react-on-rails/client'; import NavigationApp from './NavigationApp'; // Note that we're importing a different RouterApp than in serverRegistration.js @@ -71,7 +71,7 @@ Note that you should not register a renderer on the server, since there won't be #### RouterAppRenderer.jsx ```jsx -import ReactOnRails from 'react-on-rails'; +import ReactOnRails from 'react-on-rails/client'; import React from 'react'; import ReactDOM from 'react-dom'; import Router from 'react-router/lib/Router'; diff --git a/lib/generators/react_on_rails/dev_tests_generator.rb b/lib/generators/react_on_rails/dev_tests_generator.rb index 68cd97fab7..3a20a2b72e 100644 --- a/lib/generators/react_on_rails/dev_tests_generator.rb +++ b/lib/generators/react_on_rails/dev_tests_generator.rb @@ -47,14 +47,10 @@ def replace_prerender_if_server_rendering def add_yarn_relative_install_script_in_package_json package_json = File.join(destination_root, "package.json") - contents = File.read(package_json) - replacement_value = <<-STRING - "scripts": { - "postinstall": "yalc link react-on-rails", - STRING - new_client_package_json_contents = contents.gsub(/ {2}"scripts": {/, - replacement_value) - File.open(package_json, "w+") { |f| f.puts new_client_package_json_contents } + contents = JSON.parse(File.read(package_json)) + contents["scripts"] ||= {} + contents["scripts"]["postinstall"] = "yalc link react-on-rails" + File.open(package_json, "w+") { |f| f.puts JSON.pretty_generate(contents) } end end end diff --git a/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt b/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt index 379de1f4fa..d20e720f2d 100644 --- a/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt +++ b/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt @@ -1,4 +1,4 @@ -import ReactOnRails from 'react-on-rails'; +import ReactOnRails from 'react-on-rails/client'; import <%= config[:component_name] %> from '<%= config[:app_relative_path] %>'; diff --git a/lib/react_on_rails/packs_generator.rb b/lib/react_on_rails/packs_generator.rb index 2db3d6b0c9..de149ecf1c 100644 --- a/lib/react_on_rails/packs_generator.rb +++ b/lib/react_on_rails/packs_generator.rb @@ -47,7 +47,7 @@ def create_pack(file_path) def pack_file_contents(file_path) registered_component_name = component_name(file_path) <<~FILE_CONTENT - import ReactOnRails from 'react-on-rails'; + import ReactOnRails from 'react-on-rails/client'; import #{registered_component_name} from '#{relative_component_path_from_generated_pack(file_path)}'; ReactOnRails.register({#{registered_component_name}}); diff --git a/node_package/src/ReactOnRails.full.ts b/node_package/src/ReactOnRails.full.ts index c80c8dd5be..aac25a44cf 100644 --- a/node_package/src/ReactOnRails.full.ts +++ b/node_package/src/ReactOnRails.full.ts @@ -9,7 +9,10 @@ import type { import Client from './ReactOnRails.client'; if (typeof window !== 'undefined') { - console.log('Optimization opportunity: "react-on-rails" includes ~14KB of server-rendering code. Browsers may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (Requires creating a free account)'); + // warn to include a collapsed stack trace + console.warn( + 'Optimization opportunity: "react-on-rails" includes ~14KB of server-rendering code. Browsers may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (Requires creating a free account). Click this for the stack trace.', + ); } /** diff --git a/script/convert b/script/convert index a18548f808..334635e0fc 100755 --- a/script/convert +++ b/script/convert @@ -13,13 +13,13 @@ new_config = File.expand_path("../spec/dummy/config/webpacker.yml", __dir__) File.rename(old_config, new_config) -gsub_file_content("../Gemfile.development_dependencies", 'gem "shakapacker", "8.0.0"', 'gem "shakapacker", "6.6.0"') +gsub_file_content("../Gemfile.development_dependencies", /gem "shakapacker", "[^"]*"/, 'gem "shakapacker", "6.6.0"') # The below packages don't work on the oldest supported Node version and aren't needed there anyway gsub_file_content("../package.json", /"knip": "[^"]*",/, "") gsub_file_content("../package.json", %r{"@arethetypeswrong/cli": "[^"]*",}, "") -gsub_file_content("../spec/dummy/package.json", '"shakapacker": "8.0.0",', '"shakapacker": "6.6.0",') +gsub_file_content("../spec/dummy/package.json", /"shakapacker": "[^"]*",/, '"shakapacker": "6.6.0",') gsub_file_content("../spec/dummy/config/webpack/commonWebpackConfig.js", /generateWebpackConfig(\(\))?/, "webpackConfig") diff --git a/spec/dummy/app/views/pages/client_side_hello_world.html.erb b/spec/dummy/app/views/pages/client_side_hello_world.html.erb index 596ff1d5b4..06e291d79b 100644 --- a/spec/dummy/app/views/pages/client_side_hello_world.html.erb +++ b/spec/dummy/app/views/pages/client_side_hello_world.html.erb @@ -22,7 +22,7 @@
       import HelloWorld from '../components/HelloWorld';
-      import ReactOnRails from 'react-on-rails';
+      import ReactOnRails from 'react-on-rails/client';
       ReactOnRails.register({ HelloWorld });
     
diff --git a/spec/dummy/app/views/pages/server_side_hello_world.html.erb b/spec/dummy/app/views/pages/server_side_hello_world.html.erb index f77853e041..8dcb1ea96e 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world.html.erb @@ -48,7 +48,7 @@
       import HelloWorld from '../components/HelloWorld';
-      import ReactOnRails from 'react-on-rails';
+      import ReactOnRails from 'react-on-rails/client';
       ReactOnRails.register({ HelloWorld });
     
diff --git a/spec/dummy/app/views/pages/server_side_redux_app.html.erb b/spec/dummy/app/views/pages/server_side_redux_app.html.erb index d9c96b394d..b11ad675f8 100644 --- a/spec/dummy/app/views/pages/server_side_redux_app.html.erb +++ b/spec/dummy/app/views/pages/server_side_redux_app.html.erb @@ -37,7 +37,7 @@
     import ReduxApp from './ClientReduxApp';
-    import ReactOnRails from 'react-on-rails';
+    import ReactOnRails from 'react-on-rails/client';
     ReactOnRails.register({ ReduxApp });
     
diff --git a/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb b/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb index 494610d561..dec8fb17db 100644 --- a/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb +++ b/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb @@ -43,7 +43,7 @@
     import ReduxApp from './ClientReduxApp';
-    import ReactOnRails from 'react-on-rails';
+    import ReactOnRails from 'react-on-rails/client';
     ReactOnRails.register({ ReduxApp });
     
diff --git a/spec/dummy/app/views/pages/xhr_refresh.html.erb b/spec/dummy/app/views/pages/xhr_refresh.html.erb index f46cf080cc..fdad0ee637 100644 --- a/spec/dummy/app/views/pages/xhr_refresh.html.erb +++ b/spec/dummy/app/views/pages/xhr_refresh.html.erb @@ -32,7 +32,7 @@
       import HellowWorldRehydratable from '../components/HellowWorldRehydratable';
-      import ReactOnRails from 'react-on-rails';
+      import ReactOnRails from 'react-on-rails/client';
       ReactOnRails.register({ HellowWorldRehydratable });
     
diff --git a/spec/dummy/client/app/startup/HelloWorldRehydratable.jsx b/spec/dummy/client/app/startup/HelloWorldRehydratable.jsx index e433d309ac..8ebe2f9e3b 100644 --- a/spec/dummy/client/app/startup/HelloWorldRehydratable.jsx +++ b/spec/dummy/client/app/startup/HelloWorldRehydratable.jsx @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; -import ReactOnRails from 'react-on-rails'; +import ReactOnRails from 'react-on-rails/client'; import RailsContext from '../components/RailsContext'; class HelloWorldRehydratable extends React.Component { diff --git a/spec/dummy/client/app/startup/ReduxSharedStoreApp.client.jsx b/spec/dummy/client/app/startup/ReduxSharedStoreApp.client.jsx index c278dcd23e..1b1acdb811 100644 --- a/spec/dummy/client/app/startup/ReduxSharedStoreApp.client.jsx +++ b/spec/dummy/client/app/startup/ReduxSharedStoreApp.client.jsx @@ -1,9 +1,9 @@ -// Top level component for client side. -// Compare this to the ./ServerApp.jsx file which is used for server side rendering. +// Top level component for the client side. +// Compare this to the ./ReduxSharedStoreApp.server.jsx file which is used for server side rendering. import React from 'react'; import { Provider } from 'react-redux'; -import ReactOnRails from 'react-on-rails'; +import ReactOnRails from 'react-on-rails/client'; import ReactDOMClient from 'react-dom/client'; import HelloWorldContainer from '../components/HelloWorldContainer'; diff --git a/spec/dummy/client/app/startup/ReduxSharedStoreApp.server.jsx b/spec/dummy/client/app/startup/ReduxSharedStoreApp.server.jsx index 1f2d3b11c6..5982ab4415 100644 --- a/spec/dummy/client/app/startup/ReduxSharedStoreApp.server.jsx +++ b/spec/dummy/client/app/startup/ReduxSharedStoreApp.server.jsx @@ -1,5 +1,5 @@ -// Top level component for serer side. -// Compare this to the ./ClientReduxSharedStoreApp.jsx file which is used for client side rendering. +// Top level component for the server side. +// Compare this to the ./ReduxSharedStoreApp.client.jsx file which is used for client side rendering. import React from 'react'; import ReactOnRails from 'react-on-rails'; diff --git a/spec/dummy/spec/packs_generator_spec.rb b/spec/dummy/spec/packs_generator_spec.rb index f7988b3370..34f4d98b0d 100644 --- a/spec/dummy/spec/packs_generator_spec.rb +++ b/spec/dummy/spec/packs_generator_spec.rb @@ -195,6 +195,7 @@ module ReactOnRails it "generated pack for ComponentWithClientOnly uses client file for pack" do pack_content = File.read(component_pack) + expect(pack_content).to include("react-on-rails/client") expect(pack_content).to include("#{component_name}.client.jsx") expect(pack_content).not_to include("#{component_name}.jsx") expect(pack_content).not_to include("#{component_name}.server.jsx") @@ -203,6 +204,7 @@ module ReactOnRails it "generated server bundle do not have ComponentWithClientOnly registered" do generated_server_bundle_content = File.read(generated_server_bundle_file_path) + expect(generated_server_bundle_content).not_to include("react-on-rails/client") expect(generated_server_bundle_content).not_to include("#{component_name}.jsx") expect(generated_server_bundle_content).not_to include("#{component_name}.client.jsx") expect(generated_server_bundle_content).not_to include("#{component_name}.server.jsx")