From 782e5c7985f034d86cbaad2897dc33ee290e4a8c Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 14 Oct 2018 12:34:13 -1000 Subject: [PATCH] Server Side rendering disabled if HMR running (#1156) Reasonable to skip server rendering when HMR is turned on and code for server-rendering comes from webpack-dev-server. That code cannot run server-side. This change still allows the situation of HMR when dual webpack configs. --- CHANGELOG.md | 8 +++++- SUMMARY.md | 2 +- ...ading-rails-development-asset-pipeline.md} | 14 ++--------- .../manual-installation-overview.md | 2 +- docs/tutorial.md | 24 +++++++++++++++--- lib/react_on_rails/helper.rb | 4 ++- .../ruby_embedded_java_script.rb | 25 +++++++++++-------- lib/react_on_rails/utils.rb | 4 +++ lib/react_on_rails/webpacker_utils.rb | 5 ++++ 9 files changed, 59 insertions(+), 29 deletions(-) rename docs/additional-reading/{hot-reloading-rails-development.md => hot-reloading-rails-development-asset-pipeline.md} (74%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7cdf7763..0b4e22ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ Changes since last non-beta release. *Please add entries here for your pull requests that are not yet released.* +### [11.1.8] - 2018-10-14 + +#### Improved +- Improved tutorial and support for HMR when using `rails/webpacker` for Webpack configuration. [PR 1156](https://github.com/shakacode/react_on_rails/pull/1156) by [justin808](https://github.com/justin808). + ### [11.1.7] - 2018-10-10 #### Fixed - Fixed bug where intl parsing would fail when trying to parse integers or blank entries. by [sepehr500](https://github.com/sepehr500) @@ -834,7 +839,8 @@ Best done with Object destructing: ##### Fixed - Fix several generator related issues. -[Unreleased]: https://github.com/shakacode/react_on_rails/compare/11.1.7...master +[Unreleased]: https://github.com/shakacode/react_on_rails/compare/11.1.8...master +[11.1.8]: https://github.com/shakacode/react_on_rails/compare/11.1.7...11.1.8 [11.1.7]: https://github.com/shakacode/react_on_rails/compare/11.1.6...11.1.7 [11.1.6]: https://github.com/shakacode/react_on_rails/compare/11.1.5...11.1.6 [11.1.5]: https://github.com/shakacode/react_on_rails/compare/11.1.4...11.1.5 diff --git a/SUMMARY.md b/SUMMARY.md index 957daa49e..60c7f1683 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -52,7 +52,7 @@ + [Setting up Hot Reloading during Rails Development, API docs](./docs/api/ruby-api-hot-reload-view-helpers.md) + [Developing with the Webpack Dev Server](./docs/additional-reading/webpack-dev-server.md) + [Webpack, the Asset Pipeline, and Using Assets w/ React](./docs/additional-reading/rails-assets-relative-paths.md) - + [Hot Reloading of Assets For Rails Development](./docs/additional-reading/hot-reloading-rails-development.md) + + [Hot Reloading of Assets For Rails Development for Asset Pipeline](docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md) ## **[CONTRIBUTING](CONTRIBUTING.md)** + [Generator Testing](./docs/contributor-info/generator-testing.md) diff --git a/docs/additional-reading/hot-reloading-rails-development.md b/docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md similarity index 74% rename from docs/additional-reading/hot-reloading-rails-development.md rename to docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md index e5a3f870e..472d986db 100644 --- a/docs/additional-reading/hot-reloading-rails-development.md +++ b/docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md @@ -1,19 +1,9 @@ -# Live Reloading vs. Hot Reloading (aka HMR) - -The use of the [webpack-dev-server](https://webpack.js.org/configuration/dev-server/) provides "Live Reloading" by default. The difference between live and hot reloading is that live reloading will act similarly to hitting refresh in the browser. Hot reloading will attempt to preserve the state of any props. - -See the Webpack document [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) for more details on the concepts of live vs. hot reloading. - -The remainder of this document discusses HMR. - -# Using the Webpacker Webpack setup - -If you are using the default Webpacker setup of running the dev server with `bin/webpack-dev-server`, see the [Webpacker Webpack Dev Server discussion of HMR](https://github.com/rails/webpacker/blob/master/docs/webpack-dev-server.md#hot-module-replacement). +*This document should only be referenced if you're **NOT** using the current technique of the rails/webpacker helpers to place your client-side assets in your `/public` directory.* # Hot Reloading of Assets For Rails Development -_Note, this document is not yet updated for React on Rails v8+. See [PR #865](https://github.com/shakacode/react_on_rails/pull/865) for a detailed example of doing hot reloading using V8+ with Webpack v2. Any volunteers to update this page? See [#772](https://github.com/shakacode/react_on_rails/issues/772) and [#361](https://github.com/shakacode/react-webpack-rails-tutorial/issues/361)._ +_See [PR #865](https://github.com/shakacode/react_on_rails/pull/865) for a detailed example of doing hot reloading using V8+ with Webpack v2. See [#772](https://github.com/shakacode/react_on_rails/issues/772) and [#361](https://github.com/shakacode/react-webpack-rails-tutorial/issues/361)._ ------ diff --git a/docs/misc-pending/manual-installation-overview.md b/docs/misc-pending/manual-installation-overview.md index 715daef61..cae08b7c6 100644 --- a/docs/misc-pending/manual-installation-overview.md +++ b/docs/misc-pending/manual-installation-overview.md @@ -24,7 +24,7 @@ The default path: `public/webpack` can be loaded with webpackConfigLoader as sho 1. Add `gem "webpacker"` to the Gemfile, run bundle. The gem provides the `stylesheet_pack_tag` and `javascript_pack_tag` helpers which is used to load the bundled assets to your layouts.[Dummy Example](../../spec/dummy/app/views/layouts/application.html.erb) 1. Configure the `config/initializers/react_on_rails.rb`. You can adjust some necessary settings and defaults. See file [spec/dummy/config/initializers/react_on_rails.rb](../../spec/dummy/config/initializers/react_on_rails.rb) for a detailed example of configuration, including comments on the different values to configure. 1. Configure your Procfiles per the example apps. These are at the root of your Rails installation. -1. Configure your top level JavaScript files for inclusion in your layout. You'll want a version that you use for static assets, and you want a file for any files in your setup that are not part of your webpack build. The reason for this is for use with hot-reloading. If you are not using hot reloading, then you only need to configure your `application.js` file to include your Webpack generated files. For more information on hot reloading, see [Hot Reloading of Assets For Rails Development](../additional-reading/hot-reloading-rails-development.md) +1. Configure your top level JavaScript files for inclusion in your layout. You'll want a version that you use for static assets, and you want a file for any files in your setup that are not part of your webpack build. The reason for this is for use with hot-reloading. If you are not using hot reloading, then you only need to configure your `application.js` file to include your Webpack generated files. For more information on hot reloading, see [Hot Reloading of Assets For Rails Development](../additional-reading/hot-reloading-rails-development-asset-pipeline.md) 1. If you are deploying to Heroku, see [heroku-deployment.md](/docs/additional-reading/heroku-deployment.md) If I missed anything, please submit a PR or file an issue. diff --git a/docs/tutorial.md b/docs/tutorial.md index 4f0ef7adb..66fd1c721 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -282,8 +282,26 @@ mv app/javascript client source_path: client ``` -At this point, you can optionally turn off server rendering and use `foreman start -f Procfile.dev-server`. +## Using HMR with the rails/webpacker setup -Hot reloading using default rails/webpacker configuration with server rendering is not supported. +Start the app using `foreman start -f Procfile.dev-server`. -Feedback is greatly appreciated! As are stars on github! If you want personalized help, don't hesitate to get in touch with us at [contact@shakacode.com](mailto:contact@shakacode.com). +When you change a JSX file and save, the browser will automatically refresh! + +So you get some basics from HMR with no code changes. If you want to go further, take a look at these links: + +* https://github.com/rails/webpacker/blob/master/docs/webpack-dev-server.md +* https://webpack.js.org/configuration/dev-server/ +* https://webpack.js.org/concepts/hot-module-replacement/ +* https://gaearon.github.io/react-hot-loader/getstarted/ +* https://github.com/gaearon/react-hot-loader + +React on Rails will automatically handle disabling server rendering if there is only one bundle file created by the Webpack development server by rails/webpacker. + +## Conclusion + +* Browse the docs either on the [gitbook](https://shakacode.gitbooks.io/react-on-rails/content/) or in the [docs directory on github](https://github.com/shakacode/react_on_rails/tree/master/docs) + +Feedback is greatly appreciated! As are stars on github! + +If you want personalized help, don't hesitate to get in touch with us at [contact@shakacode.com](mailto:contact@shakacode.com). We offer [React on Rails Pro](https://github.com/shakacode/react_on_rails/wiki) and consulting so you can focus on your app and not on how to make Webpack plus Rails work optimally. diff --git a/lib/react_on_rails/helper.rb b/lib/react_on_rails/helper.rb index 6d6dba66f..71fcc1db7 100644 --- a/lib/react_on_rails/helper.rb +++ b/lib/react_on_rails/helper.rb @@ -405,7 +405,9 @@ def props_string(props) # Returns object with values that are NOT html_safe! def server_rendered_react_component(render_options) - return { "html" => "", "consoleReplayScript" => "" } unless render_options.prerender + if !render_options.prerender || ReactOnRails::Utils.server_bundle_path_is_http? + return { "html" => "", "consoleReplayScript" => "" } + end react_component_name = render_options.react_component_name props = render_options.props diff --git a/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb b/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb index 4856ce228..9556faa61 100644 --- a/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +++ b/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb @@ -95,19 +95,21 @@ def eval_js(js_code, _render_options) end end + def read_bundle_js_code + server_js_file = ReactOnRails::Utils.server_bundle_js_file_path + File.read(server_js_file) + rescue StandardError => e + msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be "\ + "read. You may set the server_bundle_js_file in your configuration to be \"\" to "\ + "avoid this warning.\nError is: #{e}" + raise ReactOnRails::Error, msg + end + def create_js_context return if ReactOnRails.configuration.server_bundle_js_file.blank? - server_js_file = ReactOnRails::Utils.server_bundle_js_file_path + bundle_js_code = read_bundle_js_code - begin - bundle_js_code = File.read(server_js_file) - rescue StandardError => e - msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be "\ - "read. You may set the server_bundle_js_file in your configuration to be \"\" to "\ - "avoid this warning.\nError is: #{e}" - raise ReactOnRails::Error, msg - end # rubocop:disable Layout/IndentHeredoc base_js_code = <<-JS #{console_polyfill} @@ -118,7 +120,10 @@ def create_js_context file_name = "tmp/base_js_code.js" begin if ReactOnRails.configuration.trace - Rails.logger.info { "[react_on_rails] Created JavaScript context with file #{server_js_file}" } + Rails.logger.info do + "[react_on_rails] Created JavaScript context with file "\ + "#{ReactOnRails::Utils.server_bundle_js_file_path}" + end end ExecJS.compile(base_js_code) rescue StandardError => e diff --git a/lib/react_on_rails/utils.rb b/lib/react_on_rails/utils.rb index 14f9d8511..c016d1e0a 100644 --- a/lib/react_on_rails/utils.rb +++ b/lib/react_on_rails/utils.rb @@ -64,6 +64,10 @@ def self.invoke_and_exit_if_failed(cmd, failure_message) [stdout, stderr, status] end + def self.server_bundle_path_is_http? + server_bundle_js_file_path =~ %r{https?://} + end + def self.server_bundle_js_file_path # Either: # 1. Using same bundle for both server and client, so server bundle will be hashed in manifest diff --git a/lib/react_on_rails/webpacker_utils.rb b/lib/react_on_rails/webpacker_utils.rb index 69bd5639b..0be19fe78 100644 --- a/lib/react_on_rails/webpacker_utils.rb +++ b/lib/react_on_rails/webpacker_utils.rb @@ -4,6 +4,11 @@ def self.using_webpacker? ReactOnRails::Utils.gem_available?("webpacker") end + def self.dev_server_running? + return false unless using_webpacker? + Webpacker.dev_server.running? + end + def self.bundle_js_file_path_from_webpacker(bundle_name) # Note Webpacker 3.4.3 manifest lookup is inside of the public_output_path # [2] (pry) ReactOnRails::WebpackerUtils: 0> Webpacker.manifest.lookup("app-bundle.js")