diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index e25ee7819..74452782f 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -73,6 +73,7 @@ jobs: - base - shakapacker # These don't have shakapacker: + - propshaft - sprockets_3 - sprockets_4 runs-on: ubuntu-latest diff --git a/Appraisals b/Appraisals index cce17d3b3..776883488 100644 --- a/Appraisals +++ b/Appraisals @@ -1,3 +1,7 @@ +appraise 'propshaft' do + gem 'propshaft', '~> 1.0.x' +end + appraise 'sprockets_4' do gem 'sprockets', '~> 4.0.x' gem 'sprockets-rails' diff --git a/CHANGELOG.md b/CHANGELOG.md index 3401de745..2e6a5af9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog for React-Rails -If you need help upgrading `react-rails`, `webpacker` to `shakapacker`, or JS packages, contact justin@shakacode.com. We can upgrade your project and improve your development and customer experiences, allowing you to focus on building new features or fixing bugs instead. +If you need help upgrading `react-rails`, `webpacker` to `shakapacker`, or JS packages, contact justin@shakacode.com. We can upgrade your project and improve your development and customer experiences, allowing you to focus on building new features or fixing bugs instead. For an overview of working with us, see our [Client Engagement Model](https://www.shakacode.com/blog/client-engagement-model/) article and [how we bill for time](https://www.shakacode.com/blog/shortcut-jira-trello-github-toggl-time-and-task-tracking/). @@ -15,6 +15,8 @@ Changes since the last non-beta release. _Please add entries here for your pull requests that have not yet been released. Include LINKS for PRs and committers._ +- Support for Propshaft server rendering. [PR 1345](https://github.com/reactjs/react-rails/pull/1345) by [elektronaut](https://github.com/elektronaut) + ## [3.2.1] - 2024-05-16 #### Fixed diff --git a/README.md b/README.md index 967ca626a..d0d1c91cd 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ For version 2.7 documentation, visit the [2.7-stable](https://github.com/reactjs React-Rails is a flexible tool to use [React](http://facebook.github.io/react/) with Rails. The benefits: * Automatically renders React server-side and client-side * Supports [Shakapacker](https://github.com/shakacode/shakapacker) v7 +* Supports Propshaft * Supports Sprockets 4.x, 3.x * Lets you use [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html), [ES6](http://es6-features.org/), [TypeScript](https://www.typescriptlang.org/), [CoffeeScript](http://coffeescript.org/) diff --git a/gemfiles/propshaft.gemfile b/gemfiles/propshaft.gemfile new file mode 100644 index 000000000..03b39c53c --- /dev/null +++ b/gemfiles/propshaft.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "http://rubygems.org" + +gem "propshaft", "~> 1.0.x" + +gemspec path: "../" diff --git a/gemfiles/propshaft.gemfile.lock b/gemfiles/propshaft.gemfile.lock new file mode 100644 index 000000000..140b15df2 --- /dev/null +++ b/gemfiles/propshaft.gemfile.lock @@ -0,0 +1,289 @@ +PATH + remote: .. + specs: + react-rails (3.2.0) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + +GEM + remote: http://rubygems.org/ + specs: + actioncable (7.0.8.1) + actionpack (= 7.0.8.1) + activesupport (= 7.0.8.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.8.1) + actionpack (= 7.0.8.1) + activejob (= 7.0.8.1) + activerecord (= 7.0.8.1) + activestorage (= 7.0.8.1) + activesupport (= 7.0.8.1) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.8.1) + actionpack (= 7.0.8.1) + actionview (= 7.0.8.1) + activejob (= 7.0.8.1) + activesupport (= 7.0.8.1) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.8.1) + actionview (= 7.0.8.1) + activesupport (= 7.0.8.1) + rack (~> 2.0, >= 2.2.4) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.8.1) + actionpack (= 7.0.8.1) + activerecord (= 7.0.8.1) + activestorage (= 7.0.8.1) + activesupport (= 7.0.8.1) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.8.1) + activesupport (= 7.0.8.1) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.8.1) + activesupport (= 7.0.8.1) + globalid (>= 0.3.6) + activemodel (7.0.8.1) + activesupport (= 7.0.8.1) + activerecord (7.0.8.1) + activemodel (= 7.0.8.1) + activesupport (= 7.0.8.1) + activestorage (7.0.8.1) + actionpack (= 7.0.8.1) + activejob (= 7.0.8.1) + activerecord (= 7.0.8.1) + activesupport (= 7.0.8.1) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.8.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.4.1) + bundler + rake + thor (>= 0.14.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + builder (3.2.4) + byebug (11.1.3) + capybara (3.38.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + codeclimate-test-reporter (1.0.9) + simplecov (<= 0.13) + coderay (1.1.3) + coffee-rails (5.0.0) + coffee-script (>= 2.2.0) + railties (>= 5.2.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + concurrent-ruby (1.2.2) + connection_pool (2.4.0) + crass (1.0.6) + date (3.3.4) + docile (1.1.5) + erubi (1.12.0) + es5-shim-rails (4.0.1) + actionpack (>= 3.1) + railties (>= 3.1) + execjs (2.8.1) + ffi (1.15.5) + formatador (1.1.0) + gem-release (2.2.2) + globalid (1.1.0) + activesupport (>= 5.0) + guard (2.18.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.13.0) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-minitest (2.4.6) + guard-compat (~> 1.2) + minitest (>= 3.0) + i18n (1.13.0) + concurrent-ruby (~> 1.0) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + json (2.6.3) + listen (3.0.8) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + loofah (2.21.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.2.8) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.4) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.2) + minitest (5.18.0) + minitest-retry (0.2.2) + minitest (>= 5.0) + nenv (0.3.0) + net-imap (0.4.11) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.0) + net-protocol + nio4r (2.7.3) + nokogiri (1.14.3-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.14.3-x86_64-linux) + racc (~> 1.4) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + package_json (0.1.0) + propshaft (1.1.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.10.1) + byebug (~> 11.0) + pry (>= 0.13, < 0.15) + public_suffix (5.0.1) + racc (1.6.2) + rack (2.2.7) + rack-proxy (0.7.7) + rack + rack-test (2.1.0) + rack (>= 1.3) + rails (7.0.8.1) + actioncable (= 7.0.8.1) + actionmailbox (= 7.0.8.1) + actionmailer (= 7.0.8.1) + actionpack (= 7.0.8.1) + actiontext (= 7.0.8.1) + actionview (= 7.0.8.1) + activejob (= 7.0.8.1) + activemodel (= 7.0.8.1) + activerecord (= 7.0.8.1) + activestorage (= 7.0.8.1) + activesupport (= 7.0.8.1) + bundler (>= 1.15.0) + railties (= 7.0.8.1) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.5.0) + loofah (~> 2.19, >= 2.19.1) + railties (7.0.8.1) + actionpack (= 7.0.8.1) + activesupport (= 7.0.8.1) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rake (13.0.6) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + regexp_parser (2.7.0) + rexml (3.2.6) + rubyzip (2.3.2) + selenium-webdriver (4.9.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + semantic_range (3.0.0) + shellany (0.0.1) + simplecov (0.13.0) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.2) + test-unit (2.5.5) + thor (1.2.2) + tilt (2.2.0) + timeout (0.4.1) + turbo-rails (2.0.5) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.7) + +PLATFORMS + x86_64-darwin-20 + x86_64-linux + +DEPENDENCIES + appraisal + bundler (= 2.4.9) + capybara + codeclimate-test-reporter + coffee-rails + es5-shim-rails (>= 2.0.5) + gem-release + guard + guard-minitest + jbuilder + listen (~> 3.0.0) + minitest-retry + package_json + pry-byebug + rails (~> 7.0.7, >= 7.0.7.2) + react-rails! + selenium-webdriver + propshaft (~> 1.0.x) + test-unit (~> 2.5) + turbo-rails + +BUNDLED WITH + 2.4.9 diff --git a/lib/react/server_rendering/bundle_renderer.rb b/lib/react/server_rendering/bundle_renderer.rb index b52d273bd..d6cecd52a 100644 --- a/lib/react/server_rendering/bundle_renderer.rb +++ b/lib/react/server_rendering/bundle_renderer.rb @@ -4,6 +4,7 @@ require "react/server_rendering/manifest_container" require "react/server_rendering/yaml_manifest_container" require "react/server_rendering/separate_server_bundle_container" +require "react/server_rendering/propshaft_container" module React module ServerRendering @@ -103,6 +104,7 @@ def assets_precompiled? def asset_container_class return self.class.asset_container_class if self.class.asset_container_class.present? return SeparateServerBundleContainer if SeparateServerBundleContainer.compatible? + return PropshaftContainer if PropshaftContainer.compatible? return EnvironmentContainer unless assets_precompiled? diff --git a/lib/react/server_rendering/propshaft_container.rb b/lib/react/server_rendering/propshaft_container.rb new file mode 100644 index 000000000..cc534026b --- /dev/null +++ b/lib/react/server_rendering/propshaft_container.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module React + module ServerRendering + # Return asset contents by getting them from a Propshaft::Assembly instance. + class PropshaftContainer + class << self + def assembly + ::Rails.application.assets + end + + def compatible? + !!defined?(Propshaft) && assembly.is_a?(Propshaft::Assembly) + end + end + + def find_asset(path) + self.class.assembly.load_path.find(path).content.force_encoding("utf-8") + end + end + end +end diff --git a/test/react/server_rendering/propshaft_container_test.rb b/test/react/server_rendering/propshaft_container_test.rb new file mode 100644 index 000000000..3a9ec0d82 --- /dev/null +++ b/test/react/server_rendering/propshaft_container_test.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require "test_helper" +require "open-uri" + +class PropshaftContainerTest < ActiveSupport::TestCase + PropshaftHelpers.when_propshaft_available do + def test_it_loads_js_from_the_propshaft_container + container = React::ServerRendering::PropshaftContainer.new + + assert_not_empty container.find_asset("server_rendering.js") + end + end +end diff --git a/test/support/propshaft_helpers.rb b/test/support/propshaft_helpers.rb new file mode 100644 index 000000000..b4082ba5f --- /dev/null +++ b/test/support/propshaft_helpers.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module PropshaftHelpers + module_function + + def available? + !!defined?(Propshaft) + end + + def when_propshaft_available + return unless available? + + yield + end +end