Skip to content

Fix #2549: clean stale webpack config on --rspack install#2597

Merged
justin808 merged 27 commits intomasterfrom
jg-codex/fix-2549-rspack-cleanup
Mar 15, 2026
Merged

Fix #2549: clean stale webpack config on --rspack install#2597
justin808 merged 27 commits intomasterfrom
jg-codex/fix-2549-rspack-cleanup

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented Mar 13, 2026

Summary

  • remove stale files when running
  • only remove when files are known stock/generated webpack config files
  • preserve directory and warn when custom files are present
  • add generator specs for both cleanup and preservation paths

Fixes #2549

Testing

  • Inspecting 2 files
    ..

2 files inspected, no offenses detected

  • Run options: include {focus: true, locations: {"./react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb" => [559, 632]}}
    ..

Finished in 44.88 seconds (files took 1.28 seconds to load)
2 examples, 0 failures

Run options: --seed 2821

Running:

Finished in 0.000584s, 0.0000 runs/s, 0.0000 assertions/s.

0 runs, 0 assertions, 0 failures, 0 errors, 0 skips


Note

Medium Risk
Moderate risk because the generator now conditionally deletes config/webpack/ based on file/content matching, which could remove expected files if detection is wrong, though it attempts to preserve custom/unknown files and warns instead.

Overview
Fixes --rspack installs leaving behind stale config/webpack/ by adding a cleanup step that removes the directory only when it contains known stock/generated webpack configs; otherwise it preserves the directory and emits a warning listing custom/unknown files.

The generator now tracks managed webpack template files and renders templates via ERB to verify file contents before deletion, and specs add coverage for both the removal path and the preservation path when custom webpack files are present.

Written by Cursor Bugbot for commit 474a075. Configure here.

Summary by CodeRabbit

  • New Features

    • Conservative, automatic cleanup of stale Webpack config when switching to Rspack, while preserving user-customized files and using template-aware comparisons to avoid removing modified configs.
    • Automatic generation or replacement of Rspack configuration where appropriate.
  • Tests

    • Added comprehensive tests validating cleanup, preservation, legacy-file removal, and Rspack generation across transition scenarios.

@justin808 justin808 added the codex PRs created from codex-named branches label Mar 13, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds ERB-aware cleanup to the install generator: when run with --rspack, the generator detects stock config/webpack/ files by rendering templates, removes the directory if all entries are removable, and warns/preserves files that differ from managed templates.

Changes

Cohort / File(s) Summary
Webpack Config Cleanup Infrastructure
react_on_rails/lib/generators/react_on_rails/base_generator.rb
Adds MANAGED_WEBPACK_FILE_TEMPLATES, REMOVABLE_WEBPACK_FILES; requires erb; injects cleanup_stale_webpack_config_dir_for_rspack into copy_webpack_config; implements stale_webpack_config_dir, rendered_template_for_cleanup, removable_webpack_entry?, non_removable_webpack_entries, dotfile checks, and conservative removal/warning logic based on ERB-rendered template comparisons.
Cleanup Behavior Tests
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
Adds multiple --rspack test scenarios validating removal of stock config/webpack/ files, preservation of customized files (including custom webpack.config.js), removal of legacy generateWebpackConfigs.js, and correct generation/preservation of config/rspack/ outputs and shakapacker.yml state.

Sequence Diagram

sequenceDiagram
    participant Generator as ReactOnRails Generator
    participant Cleaner as Cleanup Logic
    participant ERB as ERB Template Engine
    participant FS as File System

    Generator->>Cleaner: copy_webpack_config (--rspack) calls cleanup
    Cleaner->>FS: check for `config/webpack/` directory
    alt config/webpack exists
        Cleaner->>FS: list entries in config/webpack/
        loop for each entry
            Cleaner->>ERB: render managed template for entry
            ERB-->>Cleaner: rendered template content
            Cleaner->>FS: read actual entry content
            Cleaner->>Cleaner: compare contents -> removable?
        end
        alt all entries removable
            Cleaner->>FS: remove `config/webpack/` directory
        else non-removable entries present
            Cleaner->>Generator: warn and preserve custom files
        end
    end
    Generator->>FS: generate/ensure `config/rspack/` files
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through templates, sniffed each dotted file,

ERB showed which copies matched the pile.
I nudged the stale webpack leaves away,
Kept the curious carrots, let custom ones stay. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: cleaning stale webpack config when using --rspack, matching the primary objective of issue #2549.
Linked Issues check ✅ Passed The implementation comprehensively addresses issue #2549 requirements: removes config/webpack when only stock configs exist, preserves custom files with warnings, and uses ERB template matching for verification.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the cleanup logic for stale webpack config files as required by issue #2549; no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jg-codex/fix-2549-rspack-cleanup
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 474a07528d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 13, 2026

Greptile Summary

This PR adds a cleanup_stale_webpack_config_dir_for_rspack step to the generator that removes the legacy config/webpack/ directory when switching to rspack, provided all files in it are recognizable as stock-generated (either standard Shakapacker configs or React on Rails template outputs). Custom files are preserved with a warning. The approach is conservative and safe for the common case.

Two behavioral issues were found:

  • generateWebpackConfigs.js is never identified as removable. This file is the legacy name for ServerClientOrBoth.js (used in older React on Rails versions). The removable_webpack_entry? method routes it through the standard_shakapacker_config? || react_on_rails_config? heuristic, but neither check matches its actual content (ServerClientOrBoth.js-style code uses envSpecific as a parameter, not envSpecificConfig). Any project still using the old filename will see a misleading "custom/unknown files" warning and the directory will not be cleaned up — directly breaking the stated goal of the PR for those users.

  • Template re-rendering uses current invocation flags. rendered_template_for_cleanup evaluates templates via binding, which captures use_rsc? and use_pro? from the current generator invocation. Files that were originally generated with --rsc or --pro (e.g., clientWebpackConfig.js with the RSC plugin block) won't match the re-rendered template when the user runs with just --rspack, causing those managed files to be misclassified as non-removable. This is a less critical edge case but worth documenting or mitigating.

Confidence Score: 3/5

  • Safe to merge for most users, but silently fails for projects using the legacy generateWebpackConfigs.js filename — the primary purpose of the PR is not achieved in that case.
  • The core cleanup path (stock webpack.config.js only) works correctly and is tested. However, the generateWebpackConfigs.js detection logic is definitively broken: react_on_rails_config? checks for "envSpecificConfig" or "env.nodeEnv", neither of which appears in the ServerClientOrBoth.js template content. This means the PR's cleanup will silently fail for older projects using that legacy name. The template-rendering context mismatch is a secondary concern for --rsc/--pro combined scenarios.
  • Pay close attention to react_on_rails/lib/generators/react_on_rails/base_generator.rb, specifically the removable_webpack_entry? method around lines 320–322.

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/base_generator.rb Adds webpack config cleanup logic for rspack migration, but has a logic bug where generateWebpackConfigs.js (legacy RoR-generated file) will never be recognized as removable, and template-comparison renders with current flags rather than original generation flags.
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Adds two new test contexts covering stock-file cleanup and custom-file preservation; coverage is good for the happy paths but missing a test for the generateWebpackConfigs.js legacy filename scenario.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[cleanup_stale_webpack_config_dir_for_rspack] --> B{using_rspack?}
    B -- No --> Z[Return early - no-op]
    B -- Yes --> C{Dir.exist? config/webpack}
    C -- No --> Z
    C -- Yes --> D[List non-hidden entries]
    D --> E{entries empty?}
    E -- Yes --> Z
    E -- No --> F[For each entry: removable_webpack_entry?]
    F --> G{entry in REMOVABLE_WEBPACK_FILES?}
    G -- No --> H[non_removable]
    G -- Yes --> I{Is it a file?}
    I -- No --> H
    I -- Yes --> J{entry == webpack.config.js OR generateWebpackConfigs.js}
    J -- Yes --> K[standard_shakapacker_config? OR react_on_rails_config?]
    K -- True --> L[removable]
    K -- False --> H
    J -- No --> M[MANAGED_WEBPACK_FILE_TEMPLATES lookup]
    M --> N{template found?}
    N -- No --> H
    N -- Yes --> O[rendered_template_for_cleanup - renders with CURRENT options]
    O --> P[content_matches_template?]
    P -- Match --> L
    P -- No match --> H
    H --> Q{All entries removable?}
    L --> Q
    Q -- Yes --> R[remove_dir config/webpack]
    Q -- No --> S[say_status warning - keep directory]

    style H fill:#f96,stroke:#333
    style J fill:#ff9,stroke:#333
    style O fill:#ff9,stroke:#333
    classDef bug fill:#f96
    class K bug
Loading

Last reviewed commit: 474a075

Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

PR Review: Fix stale webpack config cleanup on --rspack install

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

PR Review: Fix stale webpack config cleanup on --rspack install

Overall: The approach is well-conceived. Template-content matching to distinguish stock files from user-customised ones is the right strategy. The code is clean and includes useful specs. A few correctness issues are worth addressing before merging.

Critical

Option-dependent template rendering can mis-classify stock files as custom

rendered_template_for_cleanup renders templates using the current generator's binding, so ERB conditionals like use_rsc?, use_pro?, and shakapacker_version_9_or_higher? all reflect the current invocation flags--not the flags used when the existing files were originally generated.

Concrete failure scenario: a user originally installed with --pro (webpack), then re-runs with --rspack (without --pro). The rendered template omits Pro-specific blocks, so the content comparison fails for serverWebpackConfig.js and clientWebpackConfig.js. Those files are treated as custom, the directory is preserved, and the user gets the confusing warning even though all files were stock-generated.

The same issue applies to --rsc (rscWebpackConfig.js is in MANAGED_WEBPACK_FILE_TEMPLATES but is only generated with --rsc) and to Shakapacker version differences (shakapacker_version_9_or_higher? gates several blocks in serverWebpackConfig.js).

Possible mitigations:

  • Render each template under every meaningful combination of options and accept any match.
  • Embed a unique fingerprint comment in every generated file and test for its presence instead of a full content comparison.
  • Rely only on the standard_shakapacker_config? / react_on_rails_config? heuristics for the removal decision and drop template-content comparison entirely.

Minor

react_on_rails_config? is overly broad for deletion decisions

Matching on envSpecificConfig / env.nodeEnv marks React on Rails-style configs as safe to delete. A user who customised their webpack config while keeping the env-dispatch pattern would silently lose their work. This path should be treated as warn-and-keep rather than safe-to-delete.

The removal-path test is implicit

The spec at line 559 asserts the directory no longer exists, but it would also pass if the directory was never created. A more explicit test would assert the directory existed with at least one stock file before the generator ran, or would spy on remove_dir to confirm cleanup actually executed. Also, sharing before(:all) state with earlier examples means a prior failure can silently affect this assertion.

Custom file warning does not say which stock files would have been cleaned

When custom files are detected, the warning only lists the unknown entries. The user cannot tell that the stock files sitting next to the custom ones would have been removed if no custom files were present--making it harder to decide whether to clean up manually.

Intent of the hidden-file filter deserves a comment

Dir.children already excludes . and .., so the reject { |e| e.start_with?(".") } only skips hidden dotfiles like .gitkeep. A brief inline comment would prevent future confusion about what is being filtered.

Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
react_on_rails/lib/generators/react_on_rails/base_generator.rb (2)

335-344: Consider extracting the shared config hash.

The config hash on line 338 duplicates the one defined in copy_webpack_config (line 134). If the message changes in one place, they could diverge.

♻️ Optional: Extract shared config to a constant or method
+      TEMPLATE_CONFIG = {
+        message: "// The source code including full typescript support is available at:"
+      }.freeze
+
       def copy_webpack_config
         cleanup_stale_webpack_config_dir_for_rspack
 
         say "Adding #{using_rspack? ? 'Rspack' : 'Webpack'} config"
         base_path = "base/base"
         base_files = %w[babel.config.js
                         config/webpack/clientWebpackConfig.js
                         # ...
-        config = {
-          message: "// The source code including full typescript support is available at:"
-        }
         base_files.each do |file|
-          template("#{base_path}/#{file}.tt", destination_config_path(file), config)
+          template("#{base_path}/#{file}.tt", destination_config_path(file), TEMPLATE_CONFIG)
         end

And in rendered_template_for_cleanup:

       def rendered_template_for_cleanup(template_path)
         `@rendered_template_cache` ||= {}
         `@rendered_template_cache`[template_path] ||= begin
-          config = { message: "// The source code including full typescript support is available at:" }
           template_content = File.read(File.join(self.class.source_root, template_path))
           ERB.new(template_content, trim_mode: "-").result(binding)
         end
       end

Note: The TEMPLATE_CONFIG constant would be accessible via binding when rendering templates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/lib/generators/react_on_rails/base_generator.rb` around lines
335 - 344, The config hash used in rendered_template_for_cleanup is duplicated
from copy_webpack_config; extract that shared hash into a single source (e.g., a
constant TEMPLATE_CONFIG or a private method template_config) and replace the
inline hashes in both rendered_template_for_cleanup and copy_webpack_config to
reference it; ensure the chosen constant/method name (TEMPLATE_CONFIG or
template_config) is in scope so ERB.new(...).result(binding) can access it when
rendering templates.

320-326: Clarify or remove generateWebpackConfigs.js handling.

The case branch handles generateWebpackConfigs.js alongside webpack.config.js, but both are compared against the same webpack.config.js.tt template. Since generateWebpackConfigs.js content won't match webpack.config.js.tt, it will always be treated as non-removable (triggering a warning).

If this is intentional future-proofing, a comment would help clarify. If generateWebpackConfigs.js is not expected to exist in the wild, consider removing it from REMOVABLE_WEBPACK_FILES to avoid confusion.

🔧 Optional: Remove generateWebpackConfigs.js if unused
-      REMOVABLE_WEBPACK_FILES = (MANAGED_WEBPACK_FILE_TEMPLATES.keys +
-        %w[webpack.config.js generateWebpackConfigs.js]).freeze
+      REMOVABLE_WEBPACK_FILES = (MANAGED_WEBPACK_FILE_TEMPLATES.keys +
+        %w[webpack.config.js]).freeze

And update the case statement:

-        when "webpack.config.js", "generateWebpackConfigs.js"
+        when "webpack.config.js"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/lib/generators/react_on_rails/base_generator.rb` around lines
320 - 326, The case branch handling "generateWebpackConfigs.js" alongside
"webpack.config.js" uses the same template check (rendered_template_for_cleanup
with "base/base/config/webpack/webpack.config.js.tt") so
"generateWebpackConfigs.js" will never match and will always be treated
non-removable; either remove "generateWebpackConfigs.js" from
REMOVABLE_WEBPACK_FILES and delete its case handling, or explicitly handle it by
adding a separate template or matching logic for "generateWebpackConfigs.js"
(update the case in the method that branches on entry and adjust calls to
rendered_template_for_cleanup/content_matches_template?/standard_shakapacker_config?
accordingly), or if intentional, add a clear comment above the case explaining
the future-proofing intent referencing entry, rendered_template_for_cleanup, and
REMOVABLE_WEBPACK_FILES so maintainers understand why it’s present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@react_on_rails/lib/generators/react_on_rails/base_generator.rb`:
- Around line 335-344: The config hash used in rendered_template_for_cleanup is
duplicated from copy_webpack_config; extract that shared hash into a single
source (e.g., a constant TEMPLATE_CONFIG or a private method template_config)
and replace the inline hashes in both rendered_template_for_cleanup and
copy_webpack_config to reference it; ensure the chosen constant/method name
(TEMPLATE_CONFIG or template_config) is in scope so ERB.new(...).result(binding)
can access it when rendering templates.
- Around line 320-326: The case branch handling "generateWebpackConfigs.js"
alongside "webpack.config.js" uses the same template check
(rendered_template_for_cleanup with
"base/base/config/webpack/webpack.config.js.tt") so "generateWebpackConfigs.js"
will never match and will always be treated non-removable; either remove
"generateWebpackConfigs.js" from REMOVABLE_WEBPACK_FILES and delete its case
handling, or explicitly handle it by adding a separate template or matching
logic for "generateWebpackConfigs.js" (update the case in the method that
branches on entry and adjust calls to
rendered_template_for_cleanup/content_matches_template?/standard_shakapacker_config?
accordingly), or if intentional, add a clear comment above the case explaining
the future-proofing intent referencing entry, rendered_template_for_cleanup, and
REMOVABLE_WEBPACK_FILES so maintainers understand why it’s present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8860f048-6739-497c-92fc-79d353cfe68a

📥 Commits

Reviewing files that changed from the base of the PR and between 474a075 and 95be040.

📒 Files selected for processing (2)
  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

test comment

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

AGENTS.md

Instructions for AI coding agents working on the React on Rails codebase.

React on Rails is a Ruby gem + npm package that integrates React with Ruby on Rails, providing server-side rendering (SSR) via Node.js or ExecJS. This is a monorepo: the open-source gem lives at react_on_rails/, the npm package at packages/react-on-rails/, and the Pro package at react_on_rails_pro/.

Canonical Agent Policy

AGENTS.md is the canonical source for repository-wide agent rules:

  • Commands and test/lint workflow
  • Code style and formatting expectations
  • Git/PR boundaries and safety rules
  • Directory and documentation boundaries

Other agent-facing docs (for example CLAUDE.md) should contain only tool-specific workflow notes and link back here.
If there is a conflict, AGENTS.md wins.

Commands

# Install dependencies
bundle && pnpm install

# Build TypeScript → JavaScript
pnpm run build

# Lint (MANDATORY before every commit)
bundle exec rubocop                  # Ruby — must pass with zero offenses
pnpm run lint                        # JS/TS via ESLint
pnpm start format.listDifferent      # Check Prettier formatting
rake lint                            # All linting (Ruby + JS + formatting)

# Auto-fix formatting
rake autofix                         # Preferred for all formatting

# Run tests
rake run_rspec:gem                   # Ruby unit tests (gem code)
rake run_rspec:dummy                 # Ruby integration tests (dummy Rails app)
pnpm run test                        # JavaScript/TypeScript tests
rake                                 # Full suite (lint + all tests except examples)

# Type checking
pnpm run type-check                  # TypeScript
bundle exec rake rbs:validate        # RBS signatures

# Additional test subsets
rake run_rspec                       # All Ruby tests
rake all_but_examples                # All tests except generated examples
rake run_rspec:shakapacker_examples_basic  # Single example test

# Full initial setup
bundle && pnpm install && rake shakapacker_examples:gen_all && rake node_package && rake

# CI/workflow linting
actionlint                           # GitHub Actions lint
yamllint .github/                    # YAML lint (do NOT run RuboCop on .yml files)

# Dependency version updates
rake shakapacker:update_version[9.6.1]  # Update shakapacker across the monorepo

Updating Shakapacker

Use rake shakapacker:update_version[VERSION] to update shakapacker across the entire monorepo. This single command updates all Gemfiles, package.json files, Gemfile.lock files, and pnpm-lock.yaml. Do not manually edit individual version references — always use the rake task to keep everything in sync.

The task handles Ruby version switching for apps that require a different Ruby version (set RUBY_VERSION_MANAGER to rvm, rbenv, asdf, or mise if needed; defaults to rvm). It continues gracefully if a single lock file update fails (e.g., due to a missing Ruby version).

Testing

  • Prefer local testing over CI iteration — don't push "hopeful" fixes. Apply the 15-minute rule: if 15 more minutes of local testing would catch the issue before CI does, spend the 15 minutes.
  • Never claim a test is "fixed" without running it locally first. Use "This SHOULD fix..." or "Proposed fix (UNTESTED)" for unverified changes.
  • Ruby: RSpec. Unit tests in react_on_rails/spec/react_on_rails/, integration tests via a dummy Rails app in react_on_rails/spec/dummy/.
  • JavaScript/TypeScript: Jest. Tests in packages/react-on-rails/tests/.
  • E2E: Playwright. Tests in react_on_rails/spec/dummy/e2e/playwright/e2e/. Run with cd react_on_rails/spec/dummy && pnpm test:e2e.
  • The dummy app (react_on_rails/spec/dummy/) is a full Rails application used for integration testing. Many tests require it.

Run specific test files:

bundle exec rspec react_on_rails/spec/react_on_rails/path/to/spec.rb
cd react_on_rails/spec/dummy && bundle exec rspec spec/path/to/spec.rb

Project Structure

Directory Purpose
react_on_rails/lib/react_on_rails/ Ruby gem source — helpers, configuration, SSR pool, engine
react_on_rails/lib/generators/ Rails generators for react_on_rails:install
react_on_rails/spec/ RSpec tests (unit + integration via dummy app)
react_on_rails/spec/dummy/ Full Rails app for integration testing and E2E
packages/react-on-rails/src/ TypeScript source — client-side React integration
packages/react-on-rails/tests/ Jest tests for the npm package
react_on_rails_pro/ Pro package (separate gem + npm, own lint config)
rakelib/ Rake task definitions
docs/oss/ OSS documentation — published to the ShakaCode website
docs/pro/ Pro documentation — installation, configuration, RSC, node renderer, caching
internal/contributor-info/ Internal contributor docs (not published to the website)
internal/planning/ Internal planning docs, drafts, and historical analysis
internal/react_on_rails_pro/contributors-info/ Internal Pro contributor docs (not published to the website)
analysis/ Investigation and analysis documents (kebab-case .md files)

Code Style

Ruby (RuboCop)

Line length max 120 characters. Run bundle exec rubocop [file] to check.

Line length — break long chains:

# Bad
content = pack_content.gsub(/import.*from.*['"];/, "").gsub(/ReactOnRails\.register.*/, "")

# Good
content = pack_content.gsub(/import.*from.*['"];/, "")
                      .gsub(/ReactOnRails\.register.*/, "")

Named subjects in RSpec:

# Bad
subject { instance.method_name(arg) }

# Good
subject(:method_result) { instance.method_name(arg) }

Security violations — scope disable comments tightly:

# rubocop:disable Security/Eval
expect { evaluate(sanitized_content) }.not_to raise_error
# rubocop:enable Security/Eval

JavaScript/TypeScript

Prettier handles all formatting. Never manually format — run rake autofix instead.

Git Workflow

Branch naming: type/descriptive-name (e.g., fix/ssr-hydration-mismatch)

Commit messages: Explain why, not what. One logical change per commit.

PR creation: Use gh pr create with a clear title, summary, and test plan.

Review Workflow

For small, focused PRs (roughly 5 files changed or fewer and one clear purpose):

  • Use at most one AI reviewer that leaves inline comments. Additional AI tools should be summary-only or used manually.
  • Wait for the first full review pass to finish before pushing follow-up commits.
  • Batch review fixes into one follow-up push when practical. Do not create a new commit for each minor comment.
  • Treat as blocking only: correctness bugs, failing tests, regressions, and clear inconsistencies with adjacent code. Nits and style suggestions are optional unless a maintainer asks for them.
  • Verify language, runtime, and library claims locally before changing code in response to AI review comments.
  • Deduplicate repeated bot comments before acting on them. Fix the underlying issue once, then resolve the duplicates.
  • Rebase or merge master once, near the end of the review cycle. For CHANGELOG.md conflicts, prefer resolving them as the final step before merge.
  • When asking an agent to address review comments, instruct it to classify comments into blocking, optional, and noise, then apply only the blocking items plus any explicitly selected optional items.

Boundaries

Always

  • Run bundle exec rubocop before committing — CI will reject violations
  • Use pnpm for all JS operations — never npm or yarn
  • Use bundle exec for Ruby commands
  • Ensure all files end with a newline
  • Let Prettier and RuboCop handle formatting — never format manually

Ask First

  • Destructive git operations (force push, reset --hard, branch deletion)
  • Changes to CI workflows (.github/workflows/)
  • Changes to build configuration (package.json scripts, webpack config)
  • Modifying the Pro package (react_on_rails_pro/)

Never

  • Skip pre-commit hooks (--no-verify)
  • Commit secrets, credentials, or .env files
  • Commit package-lock.json, yarn.lock, or other non-pnpm lock files
  • Add files to the docs/ root — OSS docs go in docs/oss/ subdirectories (getting-started/, core-concepts/, building-features/, configuration/, api-reference/, deployment/, migrating/, upgrading/, misc/); Pro docs go in docs/pro/
  • Force push to main or master

Key Concept: File Suffixes vs. RSC Directive

React on Rails has two independent systems that both use "client" and "server" terminology. Do not confuse them.

1. Bundle Placement (.client. / .server. file suffixes)

A React on Rails auto-bundling feature that controls which webpack bundle imports a file. This exists independently of React Server Components and is used with or without RSC:

  • Component.client.jsx → imported only in the client bundle (browser)
  • Component.server.jsx → imported only in the server bundle (and RSC bundle when RSC enabled)
  • Component.jsx (no suffix) → imported in both bundles

This controls where the source file is loaded, nothing more. A .server.jsx file is NOT a React Server Component — it is simply a file that webpack includes in the server bundle (and the RSC bundle when RSC is enabled). These suffixes only make sense for client components, as server components exist only in the RSC bundle.

2. RSC Classification ('use client' directive)

The 'use client' directive is part of the React Server Components architecture. It marks a component as a React Client Component. Components without it are treated as React Server Components.

When auto-bundling is enabled with RSC support (Pro feature), React on Rails uses this directive to control:

  • Registration: 'use client'ReactOnRails.register(), no 'use client'registerServerComponent()
  • RSC bundling: The RSC webpack loader uses this directive to decide whether a component is included in the RSC bundle or replaced with a client reference in that bundle

The client_entrypoint? method in packs_generator.rb checks for this directive.

They Are Orthogonal

A .client.jsx file can be a React Server Component (if it lacks 'use client'), and a .server.jsx file can be a React Client Component (if it has 'use client'). In practice, paired .client./.server. files should have consistent 'use client' status because the client and server must agree on the component's RSC role for hydration to work.

Changelog

Update /CHANGELOG.md for user-visible changes only (features, bug fixes, breaking changes, deprecations, performance improvements). Do not add entries for linting, formatting, refactoring, tests, or doc fixes.

  • Format: [PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username) (no hash before PR number)
  • Pro-only changes go in the #### Pro section of /CHANGELOG.md; shared changes go in the main section only (do not duplicate into Pro)

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

Change Log

All notable changes to this project's source code will be documented in this file. Items under Unreleased is upcoming features that will be out in the next version.

This is the unified changelog for both React on Rails (open source) and React on Rails Pro.
Pro-specific changes appear under #### Pro sections within each release.
For pre-monorepo Pro history (versions 4.0.0-rc.15 and earlier), see the archived Pro CHANGELOG.

Migration instructions for the major updates can be found here. Some smaller migration information can be found here.

Want to Save Time Updating?

If you need help upgrading react_on_rails, webpacker to shakapacker, or JS packages, contact [email protected]. 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 article and how we bill for time.

If you think ShakaCode can help your project, click here to book a call with Justin Gordon, the creator of React on Rails and Shakapacker.

Contributors

Please follow the recommendations outlined at keepachangelog.com. Please use the existing headings and styling as a guide.
After a release, run /update-changelog in Claude Code to analyze commits, write entries, and create a PR. Alternatively, run bundle exec rake update_changelog to add version headers only (you must write entries manually).

Versions

Unreleased

16.4.0.rc.9 - 2026-03-12

Improved

  • Auto-install react_on_rails_pro gem for --rsc/--pro generator flags: Running rails g react_on_rails:install --rsc or --pro now automatically installs the react_on_rails_pro gem via bundle add instead of only printing an error, matching how Shakapacker is handled in the same generator. PR 2439 by justin808.
  • create-react-on-rails-app validation and test coverage: Tightened app name validation (must start with a letter), added Rails 7.0+ prerequisite validation, and expanded validator/setup test coverage (including validateAll success path). PR 2571 by justin808.

Fixed

  • Fixed bin/setup failing on pnpm workspace member directories: bin/setup now checks for the presence of pnpm-lock.yaml before running pnpm install --frozen-lockfile, preventing failures in workspace member directories (e.g., spec/dummy) where dependencies are managed by the workspace root. PR 2477 by justin808.

Changed

  • Clarified Pro-installation signaling for immediate hydration warnings: Updated Ruby/TypeScript warning text and related docs to state that railsContext.rorPro indicates Pro gem installation (not license validity), and renamed immediate_hydration_pro_license_warning to immediate_hydration_pro_install_warning (no backward-compatible alias needed since the method had no external callers). PR 2590 by justin808.

Pro

Added
  • Startup warning for unsafe compression middleware callbacks: Added a startup guard that detects Rack::Deflater or Rack::Brotli middleware with :if callbacks that iterate the response body via body.each, which can break streaming SSR/RSC and deadlock ActionController::Live. The warning includes the middleware source location and remediation guidance. PR 2554 by justin808.
  • Configurable host binding for Node Renderer Fastify worker: Added a host setting (default: process.env.RENDERER_HOST || 'localhost') to control the bind address for the Pro Node Renderer. Set it to 0.0.0.0 in containerized environments where external health checks need to reach the renderer. PR 2585 by justin808.

Changes since the last non-beta release.

Added

  • Automatic dev asset reuse for tests: When bin/dev static is running, bundle exec rspec (and Minitest) now automatically detects and reuses the fresh development assets instead of running a separate build_test_command. The TestHelper reads config/shakapacker.yml, verifies the dev manifest is static-mode (not HMR) and fresh, then temporarily overrides Shakapacker's test config to point at the dev output. No environment variables or extra commands needed — tests "just work" with bin/dev static. HMR mode (bin/dev) continues to require separate test compilation via build_test_command or bin/dev test-watch. PR 2570 by justin808.
  • TanStack Router SSR integration (Pro): Added createTanStackRouterRenderFunction and serverRenderTanStackAppAsync via react-on-rails-pro/tanstack-router for TanStack Router SSR with the Pro Node Renderer. Uses TanStack Router's public router.load() API for reliable async SSR. Requires rendering_returns_promises = true in Pro config. PR 2516 by justin808.
  • create-react-on-rails-app --rsc flow: Added --rsc support to npx create-react-on-rails-app so a single command can scaffold an RSC-ready app. The CLI now installs react_on_rails_pro, passes --rsc to react_on_rails:install, and points users to /hello_server after setup. PR 2430 by justin808.
  • Environment-variable-driven ports in Procfile templates: Procfile templates now use ${PORT:-3000} and ${SHAKAPACKER_DEV_SERVER_PORT:-3035} instead of hardcoded ports, enabling multiple worktrees to run bin/dev concurrently without port conflicts. Includes a PortSelector that auto-detects free ports when defaults are occupied, plus a generated .env.example documenting manual overrides. PR 2539 by ihabadham.
  • CSP nonce support for RSC streaming and console replay scripts: Added cspNonce to rails_context and threaded nonce values through Pro RSC streaming paths (server-side HTML stream injection and client-side console replay script insertion), with nonce sanitization. PR 2418 by justin808.

Fixed

  • CSS module SSR fixes for rspack: Fixed CSS module class name divergence between client and server bundles when using rspack. Server webpack config now filters rspack's cssExtractLoader in addition to mini-css-extract-plugin, uses spread syntax to preserve existing CSS module options when setting exportOnlyLocals: true, and adds null guards against undefined entries in rule.use arrays. Note: exportOnlyLocals: true is no longer applied when cssLoader.options.modules is falsy (disabled), which is the correct behavior but a change from prior versions. PR 2489 by justin808.
  • Fixed private_output_path not configured on fresh Shakapacker installs: When running rails g react_on_rails:install without pre-existing Shakapacker configuration, private_output_path: ssr-generated was left commented out in the generated config/shakapacker.yml. The generator now detects whether Shakapacker was just installed and passes a shakapacker_just_installed flag to BaseGenerator, which uses force: true when copying the config template to ensure the RoR version replaces Shakapacker's default. PR 2411 by ihabadham.
  • Install generator --pretend now behaves as a safe dry run: react_on_rails:install previously executed real Shakapacker setup commands (bundle add, bundle install, and rails shakapacker:install) and could crash on File.chmod because Thor pretend mode does not create files. --pretend now skips automatic Shakapacker installation and raw chmod calls so dry-run previews complete without side effects. PR 2536 by justin808.
  • Generator test defaults now consistently use build_test_command + TestHelper, with Minitest support: Fresh installs now enable config.build_test_command and wire React on Rails TestHelper for RSpec and Minitest, while generated config/shakapacker.yml sets test compile: false to avoid mixed compilation strategies by default. Doctor now validates helper wiring per framework (including mixed RSpec+Minitest apps), detects separate vs shared test/development output-path workflows, and supports FIX=true auto-fixes for the recommended setup path. Added bin/dev test-watch with auto|full|client-only modes so test watching is easier to run consistently. bin/dev help and testing docs now explicitly document both the recommended separate-output workflow and the advanced static-only shared-output workflow, including migration from manual watcher commands. PR 2513 by justin808.

Pro

Fixed
  • Fix streaming deadlock, exception masking, and cache poisoning on client disconnect: Fixed async streaming bugs where client disconnect could cause deadlocks, mask producer exceptions, or cache partial results. PR 2562 by AbanoubGhadban.

  • Handle HTTPX error responses when fetching dev-server bundle/assets for upload: During development startup races, get_form_body_for_file could receive HTTPX::ErrorResponse and still call response.body, causing an unexpected crash path. The request layer now raises ReactOnRailsPro::Error with HTTPX error details before body access and includes regression tests for local path, HTTP success, and HTTP error cases. PR 2532 by justin808.

  • Fix streaming SSR hangs and silent error absorption in RSC payload injection: Fixed two related issues: (1) streaming SSR renders hanging forever when errors occur because Node.js stream.pipe() doesn't propagate errors or closure from source to destination, and (2) errors in the RSC payload injection pipeline being silently absorbed, preventing them from reaching error reporters like Sentry. Introduced a shared safePipe utility and used 'close' events as reliable termination signals across the streaming pipeline (Node renderer, RSC payload injection, transform streams, and Ruby async task). Also added a Ruby safety net to prevent Rails request hangs when async rendering tasks raise before the first chunk. PR 2407 by AbanoubGhadban.

  • Node renderer duplicate error reports for render failures: Fixed duplicate errorReporter.message notifications when unexpected exceptions occurred in handleRenderRequest. The handler now returns an error ResponseResult instead of rethrowing, so the same failure is not reported again by worker.ts while still returning a 400 response. PR 2531 by justin808.

  • Fix RSC payload JSON corruption from Rails view annotations in development: RSC payload responses were rendered through an HTML template, so when annotate_rendered_view_with_filenames was enabled, Rails wrapped NDJSON chunks with HTML comments and broke client-side JSON.parse. The payload endpoint now renders the template in text format and serves application/x-ndjson, and a request spec covers the annotated-view scenario. If you override custom_rsc_payload_template, ensure it resolves to a text or format-neutral template (for example, .text.erb) rather than .html.erb. When RSC support is enabled, startup now also warns if Rack::Deflater is present, because response-transforming middleware can interfere with ActionController::Live NDJSON streaming. PR 2535 by justin808.

  • Pro and RSC generator flags: Added --pro and --rsc flags to rails g react_on_rails:install, plus standalone react_on_rails:pro and react_on_rails:rsc generators for upgrading existing apps to Pro and React Server Components. Includes idempotent setup modules, webpack config transforms, prerequisite validation, and example components. PR 2284 by ihabadham.

  • Auto-registration for Redux stores: Added stores_subdirectory configuration option (e.g., "ror_stores") for automatic Redux store registration, following the same pattern as component auto-registration via ror_components. Store files placed in ror_stores/ directories are automatically discovered, and packs are generated that call ReactOnRails.registerStore(), eliminating manual registration boilerplate. Includes auto_load_bundle parameter for the redux_store helper. PR 2346 by justin808.

  • create-react-on-rails-app CLI tool: New npx create-react-on-rails-app command for single-command project setup. Phase 1 supports JavaScript and TypeScript templates with npm/pnpm, orchestrating rails new + bundle add react_on_rails + rails generate react_on_rails:install with prerequisite validation and progress output. PR 2375 by justin808.

  • Extensible bin/dev precompile pattern: New alternative approach for handling precompile tasks directly in bin/dev, providing better support for projects with custom build steps (ReScript, TypeScript), direct Ruby API access via ReactOnRails::Locales.compile, and improved version manager compatibility. PR 2349 by justin808.

  • Database setup check in bin/dev: The bin/dev command now checks database connectivity before starting the development server. This provides clear error messages when the database is missing or unavailable, instead of buried errors in the logs. Note: This adds ~1-2 seconds to startup time as it spawns a Rails runner process.

    Opt-out options (for apps without databases or when faster startup is needed):

    • CLI flag: bin/dev --skip-database-check
    • Environment variable: SKIP_DATABASE_CHECK=true bin/dev
    • Configuration: config.check_database_on_dev_start = false in config/initializers/react_on_rails.rb

    PR 2340 by justin808.

Improved

  • Smarter duplicate registration warnings: Component and store registration now only warns when a different component or store is registered under an already-used name. Re-registering the same component (common with HMR) is silently accepted. PR 2354 by justin808.

Fixed

  • CSS module SSR fixes for rspack: Fixed CSS module class name divergence between client and server bundles when using rspack. Server webpack config now filters rspack's cssExtractLoader in addition to mini-css-extract-plugin, uses spread syntax to preserve existing CSS module options when setting exportOnlyLocals: true, and adds null guards against undefined entries in rule.use arrays. Note: exportOnlyLocals: true is no longer applied when cssLoader.options.modules is falsy (disabled), which is the correct behavior but a change from prior versions. PR 2489 by justin808.
  • Fixed private_output_path not configured on fresh Shakapacker installs: When running rails g react_on_rails:install without pre-existing Shakapacker configuration, private_output_path: ssr-generated was left commented out in the generated config/shakapacker.yml. The generator now detects whether Shakapacker was just installed and passes a shakapacker_just_installed flag to BaseGenerator, which uses force: true when copying the config template to ensure the RoR version replaces Shakapacker's default. PR 2411 by ihabadham.
  • Install generator --pretend now behaves as a safe dry run: react_on_rails:install previously executed real Shakapacker setup commands (bundle add, bundle install, and rails shakapacker:install) and could crash on File.chmod because Thor pretend mode does not create files. --pretend now skips automatic Shakapacker installation and raw chmod calls so dry-run previews complete without side effects. PR 2536 by justin808.
  • bin/dev hook script path resolution without Rails.root: Fixed resolve_hook_script_path failing in early startup (before Rails is initialized) by adding a project_root helper that resolves the project root via BUNDLE_GEMFILE dirname or Dir.pwd when Rails.root is unavailable. PR 2568 by ihabadham. Fixes Issue 2438.
  • Rspack generator config path: Fixed --rspack generator placing config files under config/webpack/ instead of config/rspack/, causing Shakapacker deprecation warnings. All config file destinations are now dynamically remapped based on the active bundler, and using_rspack? auto-detects rspack projects for standalone generators (react_on_rails:rsc, react_on_rails:pro). PR 2417 by justin808.
  • Precompile hook load-based execution path: Fixed the precompile hook not executing its tasks when invoked via load (as used by bin/dev) instead of direct script execution. Added a shared run_precompile_tasks entry point that works regardless of invocation method. PR 2419 by justin808. Fixes Issue 2195.
  • create-react-on-rails-app validation improvements: Tightened CLI validation to enforce Rails 7+ and app-name leading-letter requirements, with clearer error messages for invalid names containing hyphens or underscores. PR 2577 by justin808.
  • Install @babel/preset-react for non-SWC generator installs: The generator now installs @babel/preset-react as a dev dependency when the project uses Babel (not SWC) as the transpiler, fixing JSX compilation errors on fresh installs with older Shakapacker defaults. PR 2421 by justin808.
  • Fix react_on_rails:doctor false positives for Pro/SWC setups: Doctor now recognizes react-on-rails-pro npm package for presence and version sync checks, skips @babel/preset-react check when SWC is the transpiler, and fixes a nil-safety bug where missing "dependencies" in package.json silently dropped devDependencies from checks. PR 2581 by ihabadham.
  • Fixed ScoutApm instrumentation depending on Gemfile ordering. ScoutApm instrumentation for react_component, react_component_hash, and exec_server_render_js was previously installed at gem load time using defined?(ScoutApm) guards, which meant it was silently skipped if scout_apm appeared after react_on_rails in the Gemfile, and produced noisy INFO log messages if it appeared before (since ScoutApm wasn't yet initialized). Moved instrumentation into an initializer that runs after scout_apm.start, ensuring it works regardless of gem ordering and only after ScoutApm is fully configured. PR 2442 by tonyta.
  • RSC WebpackLoader with SWC transpiler: Fixed RSC WebpackLoader never being injected when using SWC (Shakapacker's default transpiler). The RSC config only handled array-based rule.use (Babel) but SWC uses a function-based rule.use, so 'use client' files passed through untransformed into the RSC bundle. Now handles both array and function loader declarations. PR 2476 by AbanoubGhadban.
  • RSC Generator Layout Wiring: Fixed MissingEntryError on fresh RSC installs where HelloServerController fell back to Rails' application.html.erb (which uses javascript_pack_tag "application" that is not created by the RSC flow). The generator now always copies hello_world.html.erb, HelloServerController explicitly uses layout "hello_world", and post-install output now shows stream_react_component for RSC installs. PR 2429 by justin808.
  • Fixed string values interpolated into generated JS code without proper escaping. All string values (component names, DOM IDs, Redux store names) embedded in server-rendering JavaScript now use .to_json instead of unescaped single-quoted interpolation, preventing potential JS breakage from special characters. PR 2440 by AbanoubGhadban.
  • Precompile Hook Detection: Fixed shakapacker_precompile_hook_configured? always returning false for apps created with the React on Rails generator. The detection logic only matched the rake task pattern (react_on_rails:generate_packs) but the generator template uses the Ruby method (generate_packs_if_stale). Now correctly detects both patterns, including resolving script file contents. PR 2282 by ihabadham.
  • Precompile Hook Self-Guard for HMR: Added self-guard to the generator template's bin/shakapacker-precompile-hook to prevent duplicate execution in HMR mode where two webpack processes (client dev-server + server watcher) each trigger the hook. The script now exits early when SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true is set by bin/dev, regardless of Shakapacker version. The version warning is now smarter: it only warns for hooks that lack the self-guard or use direct commands. Existing users: add exit 0 if ENV["SHAKAPACKER_SKIP_PRECOMPILE_HOOK"] == "true" near the top of your bin/shakapacker-precompile-hook script. PR 2388 by justin808.
  • Fix generator inheriting BUNDLE_GEMFILE from parent process: The react_on_rails:install generator now wraps bundler commands with Bundler.with_unbundled_env to prevent inheriting BUNDLE_GEMFILE from the parent process, which caused "injected gems" conflicts when running generators inside a bundled context. PR 2288 by ihabadham.
Added
  • CSP nonce for immediate hydration scripts: The immediate hydration inline <script> tags now include the CSP nonce attribute, fixing browsers blocking them when strict Content Security Policy is enabled. PR 2398 by AbanoubGhadban.
  • License verification rake task: New react_on_rails_pro:verify_license rake task for checking license status with human-readable text and JSON output (FORMAT=json) for CI/CD integration. Includes exit codes, automatic renewal warnings for licenses expiring within 30 days, and a GitHub Actions workflow example. PR 2385 by justin808.
Changed
  • Breaking: removed legacy key-file license fallback: config/react_on_rails_pro_license.key is no longer read. Move your token to the REACT_ON_RAILS_PRO_LICENSE environment variable. A migration warning is logged at startup when the legacy file is detected and the environment variable is missing. PR 2454 by ihabadham.
Improved
  • Better error messages when component is missing 'use client' with RSC. When RSC support is enabled, components without 'use client' silently crash at runtime with confusing errors. Improved error messages at multiple layers: runtime server and client bundles now include the component name and suggest adding 'use client', build-time heuristic scans for client-only patterns and emits warnings, and generated server component pack files explain the classification. PR 2403 by AbanoubGhadban.
Fixed
  • Fix streaming deadlock, exception masking, and cache poisoning on client disconnect: Fixed async streaming bugs where client disconnect could cause deadlocks, mask producer exceptions, or cache partial results. PR 2562 by AbanoubGhadban.
  • Fix StreamResponse status fallback for non-streaming errors: Fixed StreamRequest#process_response_chunks not detecting error responses when status delegation raises NoMethodError, which masked the original HTTPX error path. PR 2416 by justin808.
  • Fix empty-string license plan mismatch between Ruby and Node: Aligned Node checkPlan with Ruby check_plan so plan: "" is treated as invalid in both runtimes. Previously, an empty-string plan passed validation in Node but failed in Ruby. PR 2566 by AbanoubGhadban.
  • Handle HTTPX error responses when fetching dev-server bundle/assets for upload: During development startup races, get_form_body_for_file could receive HTTPX::ErrorResponse and still call response.body, causing an unexpected crash path. The request layer now raises ReactOnRailsPro::Error with HTTPX error details before body access and includes regression tests for local path, HTTP success, and HTTP error cases. PR 2532 by justin808.
  • Fix streaming SSR hangs and silent error absorption in RSC payload injection: Fixed two related issues: (1) streaming SSR renders hanging forever when errors occur because Node.js stream.pipe() doesn't propagate errors or closure from source to destination, and (2) errors in the RSC payload injection pipeline being silently absorbed, preventing them from reaching error reporters like Sentry. Introduced a shared safePipe utility and used 'close' events as reliable termination signals across the streaming pipeline (Node renderer, RSC payload injection, transform streams, and Ruby async task). Also added a Ruby safety net to prevent Rails request hangs when async rendering tasks raise before the first chunk. PR 2407 by AbanoubGhadban.
  • Node renderer duplicate error reports for render failures: Fixed duplicate errorReporter.message notifications when unexpected exceptions occurred in handleRenderRequest. The handler now returns an error ResponseResult instead of rethrowing, so the same failure is not reported again by worker.ts while still returning a 400 response. PR 2531 by justin808.
  • Fix RSC payload JSON corruption from Rails view annotations in development: RSC payload responses were rendered through an HTML template, so when annotate_rendered_view_with_filenames was enabled, Rails wrapped NDJSON chunks with HTML comments and broke client-side JSON.parse. The payload endpoint now renders the template in text format and serves application/x-ndjson, and a request spec covers the annotated-view scenario. If you override custom_rsc_payload_template, ensure it resolves to a text or format-neutral template (for example, .text.erb) rather than .html.erb. When RSC support is enabled, startup now also warns if Rack::Deflater is present, because response-transforming middleware can interfere with ActionController::Live NDJSON streaming. PR 2535 by justin808.
  • Fixed buildVM promise cleanup ordering in the node renderer. buildVM() cleanup now runs via promise chaining after vmCreationPromises.set(), preventing failed synchronous VM builds from leaving stale rejected promises that block retries for the same bundle path. PR 2484 by justin808.
  • Boot failure when only react_on_rails_pro is listed in the Gemfile. react_on_rails_pro.rb never explicitly required react_on_rails, relying on Bundler.require to auto-load it via the user's Gemfile. When installation docs were updated to direct users to only add react_on_rails_pro, two errors surfaced on boot: NoMethodError: undefined method 'strip_heredoc' (from license_public_key.rb) and NoMethodError: undefined method 'configure' for module ReactOnRails (from config/initializers/react_on_rails.rb). Fixed by explicitly requiring react_on_rails in react_on_rails_pro.rb, completing the same design the JS package split already established for npm. PR 2492 by ihabadham.
  • Sentry SDK v9/v10 compatibility: The node renderer Sentry integration now supports @sentry/node v9 and v10. Replaced @sentry/types import (no longer a transitive dependency in v9+) and widened peer dependency range from <9.0.0 to <11.0.0. PR 2434 by alexeyr-ci2.
  • Fixed node renderer upload race condition causing ENOENT errors and asset corruption during concurrent requests. Concurrent multipart uploads (e.g., during pod rollovers) all wrote to a single shared path (uploads/<filename>), causing file overwrites, ENOENT errors, and cross-contamination between requests. Each request now gets its own isolated upload directory (uploads/<uuid>/), eliminating all shared-path collisions. PR 2456 by AbanoubGhadban.
  • Fixed node renderer race condition between /upload-assets and render requests writing to the same bundle directory. The /upload-assets endpoint used a global lock while render requests used per-bundle locks, so both could write to the same bundle directory concurrently, risking asset corruption. Now both endpoints share the same per-bundle lock key. Also switched parallel bundle processing from Promise.all to Promise.allSettled to prevent the onResponse cleanup hook from deleting uploaded files while in-flight copies are still reading from them. PR 2464 by AbanoubGhadban.
  • Fixed TS2769 build error in node renderer onFile callback. Removed explicit this: FastifyRequest annotation that was incompatible with @fastify/multipart type definitions, fixing pnpm build and pnpm install failures on fresh runners. PR 2469 by AbanoubGhadban.
  • Fixed RSC rendering corruption when props contain $-patterns. Props containing $` (dollar-backtick), $', or $& — common in markdown with bash variables — caused String.prototype.replace() to interpret these as special replacement patterns, corrupting the generated JavaScript and hanging the RSC payload stream. Fixed by using a function replacement callback which disables all $-pattern interpretation. PR 2440 by AbanoubGhadban.
  • Fixed RSC stream tee backpressure deadlock for large payloads. Replaced pipe()-based stream teeing with manual on('data') + push() forwarding to prevent deadlocks when RSC payloads exceed the 32KB default highWaterMark buffer, which caused the stream to hang indefinitely. PR 2444 by AbanoubGhadban.

16.3.0 - 2026-02-05

Changed

  • Simplified Shakapacker version handling: Removed obsolete minimum version checks (6.5.1) and example generation pinning (8.2.0). The gemspec dependency shakapacker >= 6.0 is now the only minimum version requirement, with autobundling requiring >= 7.0.0. PR 2247 by justin808.

Fixed

  • Rspack configuration not applying to all environments. Fixed bin/switch-bundler crashing with Psych::AliasesNotEnabled on YAML files with anchors/aliases, and fixed the --rspack generator flag only updating the default section while leaving environment sections with webpack. Now uses regex replacement to update assets_bundler in all sections while preserving YAML structure. PR 2275 by ihabadham.
  • Precompile hook not configured when Shakapacker is pre-installed. Fixed the install generator not configuring the precompile_hook when Shakapacker was already installed before running rails generate react_on_rails:install. This caused missing component bundles during assets:precompile in production deployments. PR 2280 by ihabadham.
  • bin/dev failing with --route flag. Fixed bin/dev command failing with "Unknown argument" when the generator was run with a --route option. The generated script now correctly handles route arguments. PR 2273 by ihabadham.

Pro

Changed
  • License-Optional Attribution Model: React on Rails Pro now works without a license for evaluation, development, testing, and CI/CD. A paid license is only required for production deployments. Added plan field validation to both Ruby and Node.js license validators — only "paid" plan (or no plan field for backwards compatibility) is accepted. Old free licenses are now treated as invalid. Documentation overhauled across README and LICENSE_SETUP guides; removed CI_SETUP.md (CI needs no license configuration). PR 2324 by AbanoubGhadban.
Added
  • Multiple License Plan Types: License validation now supports multiple plan types beyond "paid": startup, nonprofit, education, oss, and partner. Non-paid plan types are displayed in the license validation success message (e.g., "License validated successfully (startup license)."). Includes thread-safe caching for plan type retrieval via LicenseValidator.license_plan. PR 2334 by justin808.
  • Node Renderer Master/Worker Exports: Added public master and worker exports to react-on-rails-pro-node-renderer package, allowing users to import from react-on-rails-pro-node-renderer/master and react-on-rails-pro-node-renderer/worker. PR 2326 by justin808.

16.2.1 - 2026-01-18

Fixed

  • bin/dev Route Argument Parsing: Fixed bin/dev command failing with "Unknown argument: hello_world" when run without arguments. The --route argument format was changed from two separate arguments to a single combined argument (--route=value). PR 2309 by K4sku.

Developer (Contributors Only)

  • Benchmarking in CI: A benchmark workflow will now run on all pushes to master, as well as PRs with benchmark or full-ci labels. PR 1868 by alexeyr-ci2.

16.2.0 - 2026-01-14

Breaking Changes

  • config.immediate_hydration configuration removed: The config.immediate_hydration setting in config/initializers/react_on_rails.rb has been removed. Immediate hydration is now automatically enabled for React on Rails Pro users and automatically disabled for non-Pro users.

    Migration steps:

    • Remove any config.immediate_hydration = true or config.immediate_hydration = false lines from your config/initializers/react_on_rails.rb file
    • Pro users: No action needed - immediate hydration is now enabled automatically for optimal performance
    • Non-Pro users: No action needed - standard hydration behavior continues to work as before
    • Component-level overrides: You can still override behavior per-component using react_component("MyComponent", immediate_hydration: false) or redux_store("MyStore", immediate_hydration: true)
    • If a non-Pro user explicitly sets immediate_hydration: true on a component or store, a warning will be logged and it will be enforced to fall back to standard hydration (the value will be overridden to false)

    PR 1997 by AbanoubGhadban.

  • React on Rails Core Package: Several Pro-only methods have been removed from the core package and are now exclusively available in the react-on-rails-pro package. If you're using any of the following methods, you'll need to migrate to React on Rails Pro:

    • getOrWaitForComponent()
    • getOrWaitForStore()
    • getOrWaitForStoreGenerator()
    • reactOnRailsStoreLoaded()
    • streamServerRenderedReactComponent()
    • serverRenderRSCReactComponent()

Migration Guide:

To migrate to React on Rails Pro:

  1. Install the Pro package:

    yarn add react-on-rails-pro
    # or
    npm install react-on-rails-pro
  2. Update your imports from react-on-rails to react-on-rails-pro:

    // Before
    import ReactOnRails from 'react-on-rails';
    
    // After
    import ReactOnRails from 'react-on-rails-pro';
  3. For server-side rendering, update your import paths:

    // Before
    import ReactOnRails from 'react-on-rails';
    
    // After
    import ReactOnRails from 'react-on-rails-pro';
  4. If you're using a free license, you can obtain one at React on Rails Pro License. Important: The free 3-month evaluation license is intended for personal, educational, and evaluation purposes only. It should NOT be used for production deployments. Production use requires a paid license.

Note: If you're not using any of the Pro-only methods listed above, no changes are required.

  • Pro-Specific Configurations Moved to Pro Gem: The following React Server Components (RSC) configurations have been moved from ReactOnRails.configure to ReactOnRailsPro.configure:

    • rsc_bundle_js_file - Path to the RSC bundle file
    • react_server_client_manifest_file - Path to the React server client manifest
    • react_client_manifest_file - Path to the React client manifest

    Migration: If you're using RSC features, move these configurations from your ReactOnRails.configure block to ReactOnRailsPro.configure:

    # Before
    ReactOnRails.configure do |config|
      config.rsc_bundle_js_file = "rsc-bundle.js"
      config.react_server_client_manifest_file = "react-server-client-manifest.json"
      config.react_client_manifest_file = "react-client-manifest.json"
    end
    
    # After
    ReactOnRailsPro.configure do |config|
      config.rsc_bundle_js_file = "rsc-bundle.js"
      config.react_server_client_manifest_file = "react-server-client-manifest.json"
      config.react_client_manifest_file = "react-client-manifest.json"
    end

    See the React on Rails Pro Configuration docs for more details.

  • Streaming View Helpers Moved to Pro Gem: The following view helpers have been removed from the open-source gem and are now only available in React on Rails Pro:

    • stream_react_component - Progressive SSR using React 18+ streaming
    • rsc_payload_react_component - RSC payload rendering

    These helpers are now defined exclusively in the react-on-rails-pro gem.

  • Strict Version Validation at Boot Time: Applications now fail to boot (instead of logging warnings) when package.json is misconfigured with wrong versions, missing packages, or semver wildcards. Users must use exact versions in package.json (no ^, ~, >, <, * operators). Migration: Update package.json to use exact versions matching installed gem (e.g., "16.1.1" not "^16.1.1"). PR #1881 by AbanoubGhadban.

Added

  • Shakapacker 9.0+ Private Output Path Integration: Added automatic detection and integration of Shakapacker 9.0+ private_output_path configuration. React on Rails now automatically reads private_output_path from shakapacker.yml and sets server bundle paths, eliminating manual configuration synchronization. Includes version-aware generator templates, enhanced doctor command diagnostics for configuration validation and upgrade recommendations, and improved security with enforce_private_server_bundles option. PR 2028 by justin808.

  • Rspack Support: Added --rspack flag to react_on_rails:install generator for significantly faster builds (~20x improvement with SWC). Includes unified webpack/rspack configuration templates and bin/switch-bundler utility to switch between bundlers post-installation. PR #1852 by justin808.

  • Service Dependency Checking for bin/dev: Added optional .dev-services.yml configuration to validate required external services (Redis, PostgreSQL, Elasticsearch, etc.) are running before bin/dev starts the development server. Provides clear error messages with start commands and install hints when services are missing. Zero impact if not configured - backwards compatible with all existing installations. PR 2098 by justin808.

  • CSP Nonce Support for Console Replay: Added Content Security Policy (CSP) nonce support for the consoleReplay script generated during server-side rendering. When Rails CSP is configured, the console replay script will automatically include the nonce attribute, allowing it to execute under restrictive CSP policies like script-src: 'self'. The implementation includes cross-version Rails compatibility (5.2-7.x) and defense-in-depth nonce sanitization to prevent attribute injection attacks. PR 2059 by justin808.

  • Attribution Comment: Added HTML comment attribution to Rails views containing React on Rails functionality. The comment automatically displays which version is in use (open source React on Rails or React on Rails Pro) and, for Pro users, shows the license status. This helps identify React on Rails usage across your application. PR #1857 by AbanoubGhadban.

  • Smart Error Messages with Actionable Solutions: Added intelligent Ruby-side error handling with context-aware, actionable solutions for common issues. Features include fuzzy matching for component name typos, environment-specific debugging suggestions, color-coded error formatting, and detailed troubleshooting guides for component registration, auto-bundling, hydration mismatches, server rendering errors, and Redux store issues. PR 1934 by justin808.

  • Doctor Checks for :async Loading Strategy: Added proactive diagnostic checks to the React on Rails doctor tool to detect usage of the :async loading strategy in projects without React on Rails Pro. The feature scans view files and initializer configuration, providing clear guidance to either upgrade to Pro or use alternative loading strategies like :defer or :sync to avoid component registration race conditions. PR 2010 by justin808.

Changed

  • Shakapacker 9.0.0 Upgrade: Upgraded Shakapacker from 8.2.0 to 9.0.0 with Babel transpiler configuration for compatibility. Key changes include:

    • Configured javascript_transpiler: babel in shakapacker.yml (Shakapacker 9.0 defaults to SWC which has PropTypes handling issues)
    • Added precompile hook support via bin/shakapacker-precompile-hook for ReScript builds and pack generation
    • Configured CSS Modules to use default exports (namedExport: false) for backward compatibility with existing import styles from syntax
    • Fixed webpack configuration to process SCSS rules and CSS loaders in a single pass for better performance
      PR 1904 by justin808.
  • generated_component_packs_loading_strategy now defaults based on Pro license: When using Shakapacker >= 8.2.0, the default loading strategy is now :async for Pro users and :defer for non-Pro users. This provides optimal performance for Pro users while maintaining compatibility for non-Pro users. You can still explicitly set the strategy in your configuration. PR #1993 by AbanoubGhadban.

  • Generator Configuration Modernization: Updated the generator to enable recommended configurations by default for new applications. config.build_test_command is now uncommented and set to "RAILS_ENV=test bin/shakapacker" by default, enabling automatic asset building during tests for better integration test reliability. config.auto_load_bundle = true is now set by default, enabling automatic loading of component bundles. config.components_subdirectory = "ror_components" is now set by default, organizing React components in a dedicated subdirectory. Note: These changes only affect newly generated applications. Existing applications are unaffected and do not need to make any changes. If you want to adopt these settings in an existing app, you can manually add them to your config/initializers/react_on_rails.rb file. PR 2039 by justin808.

  • Removed Babel Dependency Installation: The generator no longer installs @babel/preset-react or @babel/preset-typescript packages. Shakapacker handles JavaScript transpiler configuration (Babel, SWC, or esbuild) via the javascript_transpiler setting in shakapacker.yml. SWC is now the default transpiler and includes built-in support for React and TypeScript. Users who explicitly choose Babel will need to manually install and configure the required presets. This change reduces unnecessary dependencies and aligns with Shakapacker's modular transpiler approach. PR 2051 by justin808.

Improved

  • SWC Compiler Detection: Added intelligent detection and automatic installation of SWC transpiler packages (@swc/core and swc-loader) when the generator detects SWC configuration. For Shakapacker 9.3.0+ (where SWC is the default transpiler), required packages are now installed automatically. Includes graceful error handling and YAML parsing security improvements. PR 2135 by justin808.

  • Enhanced bin/dev Error Messages: Improved error messages when bin/dev fails by suggesting the --verbose flag for detailed debugging output. The verbose flag now properly cascades to child processes via the REACT_ON_RAILS_VERBOSE environment variable, making troubleshooting pack generation failures significantly easier. PR 2083 by justin808.

  • Automatic Precompile Hook Coordination in bin/dev: The bin/dev command now automatically runs Shakapacker's precompile_hook once before starting development processes and sets SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true to prevent duplicate execution in spawned webpack processes.

    • Eliminates the need for manual coordination, sleep hacks, and duplicate task calls in Procfile.dev
    • Users can configure expensive build tasks (like locale generation or ReScript compilation) once in config/shakapacker.yml and bin/dev handles coordination automatically
    • Includes warning for Shakapacker versions below 9.4.0 (the SHAKAPACKER_SKIP_PRECOMPILE_HOOK environment variable is only supported in 9.4.0+)
    • The SHAKAPACKER_SKIP_PRECOMPILE_HOOK environment variable is set for all spawned processes, making it available for custom scripts that need to detect when bin/dev is managing the precompile hook
    • Addresses 2091 by justin808
  • Idempotent Locale Generation: The react_on_rails:locale rake task is now idempotent, automatically skipping generation when locale files are already up-to-date. This makes it safe to call multiple times (e.g., in Shakapacker's precompile_hook) without duplicate work. Added force=true option to override timestamp checking. PR 2090 by justin808.

  • Improved Error Messages: Error messages for version mismatches and package configuration issues now include package-manager-specific installation commands (npm, yarn, pnpm, bun). PR #1881 by AbanoubGhadban.

Fixed

  • Component Registration: Fixed "component not registered" error on core react-on-rails package that could occur when components were referenced before registration completed. PR 2295 by AbanoubGhadban.

  • webpack-cli Compatibility: Fixed compatibility issue with webpack-dev-server v5 by upgrading webpack-cli from v4 to v6.0.1 and removing the deprecated @webpack-cli/serve package. Also removed deprecated https: false configuration from shakapacker.yml. PR 2291 by AbanoubGhadban.

  • Hydration Mismatch on Multiple reactOnRailsPageLoaded() Calls: Fixed hydration errors that occurred when reactOnRailsPageLoaded() was invoked multiple times for asynchronously loaded content. The fix tracks rendered components and skips re-rendering already-tracked components, while intelligently handling DOM node replacements by detecting when a node with the same ID is swapped out. Addresses issue 2210. PR 2211 by justin808.

  • TypeScript processPromise Return Type: Fixed TypeScript compilation error in serverRenderReactComponent.ts where the type checker couldn't properly narrow the union type after the isValidElement check. Added explicit type assertion to FinalHtmlResult to resolve the issue. PR 2204 by justin808.

  • connection_pool 3.0+ Compatibility: Fixed ArgumentError: wrong number of arguments when using connection_pool gem version 3.0 or later. The gem's API changed from accepting a positional hash to requiring keyword arguments. This fix ensures compatibility with both older and newer versions of connection_pool. Addresses issue 2185. PR 2125 by justin808.

  • RSpec Helper Optimization with Private SSR Directories: Fixed RSpec helper optimization bug that caused tests to run with stale server-side code when server bundles are stored in private ssr-generated/ directories. The helper now automatically monitors server bundles and other critical files, ensuring proper rebuild detection even when assets are in separate directories from the manifest. PR 1838 by justin808.

  • Pack Generation in bin/dev from Bundler Context: Fixed pack generation failing with "Could not find command 'react_on_rails:generate_packs'" when running bin/dev from within a Bundler context. The fix wraps the bundle exec call with Bundler.with_unbundled_env to prevent interception. PR 2085 by justin808.

  • bin/dev Process Manager Detection: Fixed misleading "Process Manager Not Found" error when overmind is installed but exits with a non-zero code (e.g., when a Procfile process crashes). The error message now correctly distinguishes between a missing process manager and a process manager that ran but failed. PR 2087 by justin808.

  • Doctor Command Version Mismatch Detection: Fixed false version mismatch warnings in rake react_on_rails:doctor when using beta/prerelease versions. The command now correctly recognizes that gem version 16.2.0.beta.10 matches npm version 16.2.0-beta.10 using proper semver conversion instead of string normalization that stripped prerelease identifiers. PR 2064 by ihabadham.

  • Rails 5.2-6.0 Compatibility: Fixed compatibility with Rails 5.2-6.0 by adding polyfill for compact_blank method (introduced in Rails 6.1). Also refactored webpack asset handling to conditionally include React on Rails Pro files only when available, preventing NoMethodErrors in open-source installations. PR 2058 by justin808.

  • Duplicate Rake Task Execution: Fixed rake tasks executing twice during asset precompilation and other rake operations. Rails Engine was loading task files twice: once via explicit load calls in the rake_tasks block (Railtie layer) and once via automatic file loading from lib/tasks/ (Engine layer). This caused react_on_rails:assets:webpack, react_on_rails:generate_packs, and react_on_rails:locale tasks to run twice, significantly increasing build times. Removed explicit load calls and now rely on Rails Engine's standard auto-loading behavior. PR 2052 by justin808.

Security

  • Development Dependencies Security: Addressed 58 Dependabot vulnerabilities in dev/test dependencies including critical issues in webpack (DOM clobbering XSS), nokogiri (libxml2 CVEs), activestorage, rack (5 DoS vulnerabilities), and jws (HMAC signature bypass). These changes only affect development environments—production gem code is unchanged. PR 2261 by ihabadham.

  • Command Injection Protection: Added security hardening to prevent potential command injection in package manager commands. PR #1881 by AbanoubGhadban.

Documentation

  • Simplified Configuration Files: Improved configuration documentation and generator template for better clarity and usability. Reduced generator template from 67 to 42 lines (37% reduction). Added comprehensive testing configuration guide. Reorganized configuration docs into Essential vs Advanced sections. Enhanced Doctor program with diagnostics for server rendering and test compilation consistency. PR #2011 by justin808.

Developer (Contributors Only)

  • Monorepo Structure Reorganization: Restructured the monorepo to use two top-level product directories (react_on_rails/ and react_on_rails_pro/) instead of mixing source files at the root level. This improves organization and clarity for contributors working on either the open-source or Pro versions. Important for contributors: If you have an existing clone of the repository, you may need to update your IDE exclusion patterns and paths. See the updated CLAUDE.md for current project structure. PR 2114 by justin808.

  • Package Manager Migration to pnpm: Migrated the monorepo from Yarn Classic to pnpm for improved dependency management and faster installs. Contributors should reinstall dependencies with pnpm install after pulling this change. PR 2121 by justin808.

  • Bundle Size CI Monitoring: Added automated bundle size tracking to CI using size-limit. Compares PR bundle sizes against the base branch and fails if any package increases by more than 0.5KB. Includes local comparison tool (bin/compare-bundle-sizes) and bypass mechanism (bin/skip-bundle-size-check) for intentional size increases. PR 2149 by AbanoubGhadban.

  • Download Time CI Monitoring: Added automated download time tracking to CI using size-limit. Compares PR client import download times against the base branch and fails if any import increases by more than 10%. PR 2160 by AbanoubGhadban.

Pro

Includes all features from the React on Rails Pro 4.0.0 release series (previously released as 4.0.0-rc.6 through 4.0.0-rc.15). For pre-monorepo Pro history, see the archived Pro CHANGELOG.

Breaking Changes
  • Node Renderer Version Validation: Remote node renderer now validates gem version at request time. Version mismatches in development return 412 Precondition Failed (production allows with warning). Ensure react_on_rails_pro gem and @shakacode-tools/react-on-rails-pro-node-renderer package versions match. PR #1881 by AbanoubGhadban.
  • Prerender caching for streaming: config.prerender_caching now controls caching for both streamed and non-streamed components. To disable for individual renders, pass internal_option(:skip_prerender_cache).
  • ReactOnRailsPro::Utils#copy_assets return value: Now returns nil instead of Response object, throwing an error on failure instead. PR 422 by AbanoubGhadban.
  • Added async gem dependency (>= 2.6) for concurrent streaming.
  • Dropped support for EOL'd Ruby 2.7. PR 365 by ahangarha.
  • Dropped support for React on Rails below 14.0.4. PR 415 by rameziophobia.
Added
  • React Server Components Support: Full RSC integration for Rails apps — reduce client bundle sizes and enable powerful data fetching patterns. See the tutorial. PR 422 by AbanoubGhadban.
  • Streaming Server Rendering: stream_view_containing_react_components and stream_react_component helpers for progressive page loading. Includes console log replay, error handling during streaming (initial render and suspense boundaries), and raise_non_shell_server_rendering_errors configuration. PR 407, PR #429, PR #432 by AbanoubGhadban.
  • Async React Component Rendering: async_react_component and cached_async_react_component helpers for concurrent component rendering. Multiple components execute HTTP requests to the Node renderer in parallel. Requires ReactOnRailsPro::AsyncRendering concern in controller. PR 2139 by AbanoubGhadban.
  • Concurrent Streaming Performance: Concurrent draining of streamed React components using the async gem with producer-consumer pattern and bounded buffering. PR 2015 by ihabadham.
  • License Validation System: JWT-based license validation with offline verification using RSA-256 signatures. PR #1857 by AbanoubGhadban.
  • Improved RSC Payload Error Handling: Errors during RSC payload generation are now transferred to Rails with error messages and stack traces. PR #1888 by AbanoubGhadban.
  • cached_stream_react_component helper for cached streaming.
  • config.concurrent_component_streaming_buffer_size option (defaults to 64) for concurrent streaming memory buffer control.
  • replayServerAsyncOperationLogs configuration for capturing async operation console output during SSR. PR 440 by AbanoubGhadban.
Changed
  • immediate_hydration auto-enabled for Pro users: The configuration option has been removed; immediate hydration is now automatically enabled for Pro users and disabled for non-Pro users. Component-level overrides still supported. PR 1997 by AbanoubGhadban.
  • RSC rendering flow improvements: Eliminated double rendering, reduced HTTP requests, added multi-bundle upload via communication protocol v2.0.0. PR 515 by AbanoubGhadban.
  • Node Renderer: Express to Fastify: Converted worker from Express to Fastify. PR 398 by alexeyr-ci.
  • Fastify 5 upgrade: Default with fallback to Fastify 4 on older Node versions. PR 478 by alexeyr-ci.
  • Pino logging: Replaced Winston, aligning with Fastify. PR 479 by alexeyr-ci.
  • HTTP/2 Cleartext communication with Node Renderer. PR 392 by alexeyr-ci.
  • HTTPX for Node renderer: Converted from Net::HTTP to HTTPX. PR 452 by alexeyr-ci. Upgraded to ~> 1.5. PR 520 by AbanoubGhadban.
  • Error reporting/tracing overhaul: See the docs. PR 471 by alexeyr-ci.
  • Added fastifyServerOptions config and set bodyLimit to 100 MB by default. PR 511 by Romex91.
  • Renamed includeTimerPolyfills to stubTimers. Fail immediately on obsolete config options. PR 506 by alexeyr-ci.
  • Shakapacker 8.0.0 support (drops 6.x). PR 415 by rameziophobia.
Fixed
  • Thread-Safe Connection Management: Fixed race conditions in ReactOnRailsPro::Request using double-checked locking. PR 2259 by AbanoubGhadban.
  • JSON Parse Race Condition in Immediate Hydration: Fixed race condition where immediate_hydration could parse incomplete JSON during HTML streaming. Uses nextSibling check to verify props script completion. PR 2290 by AbanoubGhadban.
  • Legacy Module Resolver Compatibility: Added main field to Pro package.json files for legacy module resolvers. PR 2256 by ihabadham.
  • Client Disconnect Handling for Streaming: Catches IOError/Errno::EPIPE on disconnect, stops barrier to cancel producer tasks. PR 2137 by justin808.
  • Node Renderer Worker Restart: Fixed "descriptor closed" error during restarts. Workers now perform graceful shutdowns with configurable gracefulWorkerRestartTimeout. PR 1970 by AbanoubGhadban.
  • Body Duplication Bug On Streaming: Fixed bug when node renderer connection closed after partial streaming. PR 1995 by AbanoubGhadban.
  • Fixed compatibility with httpx 1.6.x by requiring http-2 >= 1.1.1. PR 2141 by AbanoubGhadban.
  • Fixed unnecessary bundle requests when RSC is disabled. PR 545 by AbanoubGhadban.
  • Made default bundle paths consistent between node-renderer and Rails. PR 399 by alexeyr-ci.
Security
Deprecated
  • Node Renderer bundlePath: Renamed to serverBundleCachePath. Old option continues to work with deprecation warning. PR 2008 by justin808.

16.1.1 - 2025-09-24

Bug Fixes

  • React Server Components: Fixed bug in resolving react-server-client-manifest.json file path. The manifest file path is now correctly resolved using bundle_js_file_path for improved configuration flexibility and consistency in bundle management. PR 1818 by AbanoubGhadban

16.1.0 - 2025-09-23

New Features

  • Server Bundle Security: Added new configuration options for enhanced server bundle security and organization:

    • server_bundle_output_path: Configurable directory (relative to the Rails root) for server bundle output (default: "ssr-generated"). If set to nil, the server bundle will be loaded from the same public directory as client bundles. PR 1798 by justin808
    • enforce_private_server_bundles: When enabled, ensures server bundles are only loaded from private directories outside the public folder (default: false for backward compatibility) PR 1798 by justin808
  • Improved Bundle Path Resolution: Bundle path resolution for server bundles now works as follows:

    • If server_bundle_output_path is set, the server bundle is loaded from that directory.
    • If server_bundle_output_path is not set, the server bundle falls back to the client bundle directory (typically the public output path).
    • If enforce_private_server_bundles is enabled:
      • The server bundle will only be loaded from the private directory specified by server_bundle_output_path.
      • If the bundle is not found there, it will not fall back to the public directory.
    • If enforce_private_server_bundles is not enabled and the bundle is not found in the private directory, it will fall back to the public directory.
    • This logic ensures that, when strict enforcement is enabled, server bundles are never loaded from public directories, improving security and clarity of bundle resolution. PR 1798 by justin808
  • react_on_rails:doctor rake task: New diagnostic command to validate React on Rails setup and identify configuration issues. Provides comprehensive checks for environment prerequisites, dependencies, Rails integration, and Webpack configuration. Use rake react_on_rails:doctor to diagnose your setup, with optional VERBOSE=true for detailed output. PR 1791 by AbanoubGhadban

Deprecations

  • Deprecated generated_assets_dirs configuration: The legacy config.generated_assets_dirs option is now deprecated and will show a deprecation warning if used. Since Shakapacker is now required, asset paths are automatically determined from shakapacker.yml configuration. Remove any config.generated_assets_dirs from your config/initializers/react_on_rails.rb file. Use public_output_path in config/shakapacker.yml to customize asset output location instead. PR 1798 by justin808

API Improvements

  • Method Naming Clarification: Added public_bundles_full_path method to clarify bundle path handling:
    • public_bundles_full_path: New method specifically for webpack bundles in public directories
    • generated_assets_full_path: Now deprecated (backwards-compatible alias)
    • This eliminates confusion between webpack bundles and general Rails public assets PR 1798 by justin808

Security Enhancements

  • Private Server Bundle Enforcement: When enforce_private_server_bundles is enabled, server bundles bypass public directory fallbacks and are only loaded from designated private locations PR 1798 by justin808
  • Path Validation: Added validation to ensure server_bundle_output_path points to private directories when enforcement is enabled PR 1798 by justin808
  • Fixed command injection vulnerabilities: Replaced unsafe string interpolation in generator package installation commands with secure array-based system calls PR 1786 by justin808
  • Improved input validation: Enhanced package manager validation and argument sanitization across all generators PR 1786 by justin808
  • Hardened DOM selectors: Using CSS.escape() and proper JavaScript escaping for XSS protection PR 1791 by AbanoubGhadban

Pro License Features

  • Core/Pro separation: Moved Pro features into dedicated lib/react_on_rails/pro/ and node_package/src/pro/ directories with clear licensing boundaries (now separated into packages/react-on-rails-pro/ package) PR 1791 by AbanoubGhadban
  • Runtime license validation: Implemented Pro license gating with graceful fallback to core functionality when Pro license unavailable PR 1791 by AbanoubGhadban
  • Enhanced immediate hydration: Improved immediate hydration functionality with Pro license validation and warning badges PR 1791 by AbanoubGhadban
  • License documentation: Added NOTICE files in Pro directories referencing canonical REACT-ON-RAILS-PRO-LICENSE.md PR 1791 by AbanoubGhadban

Generator Improvements

  • Modern TypeScript patterns: Generators now produce more idiomatic TypeScript code with improved type inference instead of explicit type annotations PR 1786 by justin808
  • Optimized tsconfig.json: Updated compiler options to use "moduleResolution": "bundler" for better bundler compatibility PR 1786 by justin808
  • Enhanced Redux TypeScript integration: Improved type safety and modern React patterns (useMemo, type-only imports) PR 1786 by justin808
  • Smart bin/dev defaults: Generated bin/dev script now automatically navigates to /hello_world route for immediate component visibility PR 1786 by justin808
  • Better component templates: Removed unnecessary type annotations while maintaining type safety through TypeScript's inference PR 1786 by justin808
  • Cleaner generated code: Streamlined templates following modern React and TypeScript best practices PR 1786 by justin808
  • Improved helper methods: Added reusable component_extension helper for consistent file extension handling PR 1786 by justin808

Bug Fixes

  • Doctor rake task: Fixed LoadError in rake react_on_rails:doctor when using packaged gem. The task was trying to require excluded rakelib/task_helpers file. PR 1795 by justin808
  • Packs generator: Fixed error when server_bundle_js_file configuration is empty (default). Added safety check to prevent attempting operations on invalid file paths when server-side rendering is not configured. PR 1802 by justin808
  • Non-Packer Environment Compatibility: Fixed potential NoMethodError when using bundle path resolution in environments without Shakapacker PR 1798 by justin808
  • Shakapacker version requirements: Fixed inconsistent version requirements between basic pack generation (6.5.1+) and advanced auto-bundling features (7.0.0+). Added backward compatibility for users on Shakapacker 6.5.1-6.9.x while providing clear upgrade guidance for advanced features. Added new constants MINIMUM_SHAKAPACKER_VERSION_FOR_AUTO_BUNDLING and improved version checking performance with caching. PR 1798 by justin808

Code Improvements

  • PackerUtils abstraction removal: Removed unnecessary PackerUtils.packer abstraction method and replaced all calls with direct ::Shakapacker usage. This simplifies the codebase by eliminating an abstraction layer that was originally created to support multiple webpack tools but is no longer needed since we only support Shakapacker. All tests updated accordingly. PR 1798 by claude-code
  • Architecture refactoring: Centralized Pro utilities and clean separation between core and Pro helper functionality PR 1791 by AbanoubGhadban

16.0.0 - 2025-09-16

React on Rails v16 is a major release that modernizes the library with ESM support, removes legacy Webpacker compatibility, and introduces significant performance improvements. This release builds on the foundation of v14 with enhanced RSC (React Server Components) support and streamlined configuration.

See Release Notes for complete migration guide.

Major Enhancements

🚀 React Server Components (RSC) -- Requires React on Rails Pro

  • Enhanced RSC rendering flow: Eliminated double rendering and reduced HTTP requests
  • RSCRoute component: Seamless server-side rendering with automatic payload injection and hydration PR 1696 by AbanoubGhadban
  • Optimized RSC payload injection: Now injected after component HTML markup for better performance PR 1738 by AbanoubGhadban
  • Communication protocol v2.0.0: Supports uploading multiple bundles at once for improved efficiency

⚡ Performance & Loading Strategy

  • New generated_component_packs_loading_strategy: Choose from sync, async, or defer strategies PR 1712 by AbanoubGhadban
  • Async render function support: Components can now return from async render functions PR 1720 by AbanoubGhadban
  • Optimized client imports: Generated packs now import from react-on-rails/client for better tree-shaking PR 1706 by alexeyr-ci

Developer Experience

  • Enhanced error messaging: Clearer troubleshooting steps and prominent optimization warnings
  • Modern global access: Using globalThis instead of window/global detection PR 1727 by alexeyr-ci2
  • Simplified CI configuration: Clear minimum/latest dependency naming instead of oldest/newest
  • ReactRefreshWebpackPlugin v0.6.0 support: Added conditional logic for proper configuration PR 1748 by judahmeek
  • Version validation improvements: Fixed invalid warnings with pre-release versions PR 1742 by alexeyr-ci2

Breaking Changes

🔧 Webpacker Support Removed

  • Complete removal of Webpacker support. Shakapacker >= 6.0 is now required.
  • Migration:
    • Remove webpacker gem from your Gemfile
    • Install shakapacker gem version 6.0+ (8.0+ recommended)
    • Replace bin/webpacker commands with bin/shakapacker
    • Update webpacker configuration files to shakapacker equivalents
  • Removed files: rakelib/webpacker_examples.rake, lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb

📦 Package System Modernization

  • ESM-only package: CommonJS require() no longer supported
  • Migration:
    • Replace require('react-on-rails') with import ReactOnRails from 'react-on-rails'
    • For Node.js < 20.19.0, upgrade or use dynamic imports
    • For TypeScript errors, upgrade to TypeScript 5.8+ and set module: "nodenext"

⚡ Configuration API Changes

  • defer_generated_component_packs deprecated → use generated_component_packs_loading_strategy

  • Migration:

    • defer_generated_component_packs: truegenerated_component_packs_loading_strategy: :defer
    • defer_generated_component_packs: falsegenerated_component_packs_loading_strategy: :sync
    • Recommended: generated_component_packs_loading_strategy: :async for best performance
  • force_load renamed to immediate_hydration for API clarity

  • Migration:

    • config.force_load = trueconfig.immediate_hydration = true
    • react_component(force_load: true)react_component(immediate_hydration: true)
    • redux_store(force_load: true)redux_store(immediate_hydration: true)
  • Note: immediate_hydration requires React on Rails Pro license

🔄 Async API Changes

  • ReactOnRails.reactOnRailsPageLoaded() is now async
  • Migration: Add await when calling: await ReactOnRails.reactOnRailsPageLoaded()

🏗️ Runtime Suggested Versions

  • Ruby: 3.2 - 3.4 (was 3.0 - 3.3)
  • Node.js: 20 - 22 (was 16 - 20)
  • Note: These are CI-tested versions; older versions may work but aren't guaranteed

🎯 Generator Improvements

  • Install generator now validates JavaScript package manager presence
  • Improved error handling with Thor::Error instead of exit(1)
  • Enhanced error messages with clearer troubleshooting steps

[15.0.0] - 2025-08-28 - RETRACTED

⚠️ This version has been retracted due to API design issues. Please upgrade directly to v16.0.0.

The force_load feature was incorrectly available without a Pro license and has been renamed to immediate_hydration for better clarity. All features from v15 are available in v16 with the corrected API.

14.2.0 - 2025-03-03

Added

  • Add export option 'react-on-rails/client' to avoid shipping server-rendering code to browsers (~5KB improvement) PR 1697 by Romex91.

Fixed

  • Fix obscure errors by introducing FULL_TEXT_ERRORS PR 1695 by Romex91.
  • Disable esModuleInterop to increase interoperability PR 1699 by alexeyr-ci.
  • Resolved 14.1.1 incompatibility with eslint & made sure that spec/dummy is linted by eslint. PR 1693 by judahmeek.

Changed

14.1.1 - 2025-01-15

Fixed

  • Separated streamServerRenderedReactComponent from the ReactOnRails object in order to stop users from getting errors during Webpack compilation about needing the stream-browserify package. PR 1680 by judahmeek.
  • Removed obsolete js-yaml peer dependency. PR 1678 by alexeyr-ci.

14.1.0 - 2025-01-06

Fixed

  • Incorrect type and confusing name for ReactOnRails.registerStore, use registerStoreGenerators instead. PR 1651 by alexeyr-ci.
  • Changed the ReactOnRails' version checker to use ReactOnRails.configuration.node_modules_location to determine the location of the package.json that the react-on-rails dependency is expected to be set by.
  • Also, all errors that would be raised by the version checking have been converted to Rails.Logger warnings to avoid any breaking changes. PR 1657 by judahmeek.
  • Enable use as a git: dependency. PR 1664 by alexeyr-ci.

Added

  • Added streaming server rendering support:
    • PR #1633 by AbanoubGhadban.
      • New stream_react_component helper for adding streamed components to views
      • New streamServerRenderedReactComponent function in the react-on-rails package that uses React 18's renderToPipeableStream API
      • Enables progressive page loading and improved performance for server-rendered React components
    • Added support for replaying console logs that occur during server rendering of streamed React components. This enables debugging of server-side rendering issues by capturing and displaying console output on the client and on the server output. PR #1647 by AbanoubGhadban.
    • Added support for handling errors happening during server rendering of streamed React components. It handles errors that happen during the initial render and errors that happen inside suspense boundaries. PR #1648 by AbanoubGhadban.
    • Added support for passing options to YAML.safe_load when loading locale files with config.i18n_yml_safe_load_options. PR #1668 by dzirtusss.

Changed

  • Console replay script generation now awaits the render request promise before generating, allowing it to capture console logs from asynchronous operations. This requires using a version of the Node renderer that supports replaying async console logs. PR #1649 by AbanoubGhadban.

14.0.5 - 2024-08-20

Fixed

14.0.4 - 2024-07-02

Improved

  • Improved dependency management by integrating package_json. PR 1639 by vaukalak.

Changed

  • Update outdated GitHub Actions to use Node.js 20.0 versions instead PR 1623 by adriangohjw.

14.0.3 - 2024-06-28

Fixed

14.0.2 - 2024-06-11

Fixed

14.0.1 - 2024-05-16

Fixed

  • Pack Generation: Added functionality that will add an import statement, if missing, to the server bundle entry point even if the auto-bundle generated files still exist PR 1610 by judahmeek.

14.0.0 - 2024-04-03

Major bump because dropping support for Ruby 2.7 and deprecated webpackConfigLoader.js.

Removed

Fixed

  • Trimmed the Gem to remove package.json which could cause superflous security warnings. PR 1605 by justin808.
  • Prevent displaying the deprecation message for using webpacker_precompile? method and webpacker:clean rake task when using Shakapacker v7+ PR 1592 by ahangarha.
  • Fixed Typescript types for ServerRenderResult, ReactComponent, RenderFunction, and RailsContext interfaces. PR 1582 & PR 1585 by kotarella1110
  • Removed a workaround in JsonOutput#escape for an no-longer supported Rails version. Additionally, removed Utils.rails_version_less_than_4_1_1
    which was only used in the workaround. PR 1580 by wwahammy

Added

13.4.0 - 2023-07-30

Fixed

  • Fixed Pack Generation logic during assets:precompile if auto_load_bundle is false & components_subdirectory is not set. PR 1567 by blackjack26 & judahmeek.

Improved

  • Improved performance by removing an unnecessary JS eval from Ruby. PR 1544 by wyattades.

Added

Changed

  • Throw error when attempting to redefine ReactOnRails. PR 1562 by rubenochiavone.
  • Prevent generating FS-based packs when component_subdirectory configuration is not present. PR 1567 by blackjack26.
  • Removed a requirement for autoloaded pack files to be generated as part of CI or deployment separate from initial Shakapacker bundling. PR 1545 by judahmeek.

13.3.5 - 2023-05-31

Fixed

  • Fixed race condition where a React component could attempt to initialize before it had been registered. PR 1540 by judahmeek.

13.3.4 - 2023-05-23

Added

  • Improved functionality of Filesystem-based pack generation & auto-bundling. Added make_generated_server_bundle_the_entrypoint configuration key. PR 1531 by judahmeek.

Removed

  • Removed unneeded HMR=true from Procfile.dev in install template PR 1537 by ahangarha.

13.3.3 - 2023-03-21

Fixed

13.3.2 - 2023-02-24

Fixed

  • Fixed the bug in bin/dev and bin/dev-static scripts by using system instead of exec and remove option to pass arguments PR 1519 by ahangarha.

13.3.1 - 2023-01-30

Added

  • Optimized ReactOnRails::TestHelper's RSpec integration using when_first_matching_example_defined. PR 1496 by mcls.

Fixed

13.3.0 - 2023-01-29

Fixed

  • Fixed pack not found warning while using react_component and react_component_hash helpers, even when corresponding chunks are present. PR 1511 by pulkitkkr.
  • Fixed FS-based packs generation functionality to trigger pack generation on the creation of a new React component inside components_subdirectory. PR 1506 by pulkitkkr.
  • Upgrade several JS dependencies to fix security issues. PR 1514 by ahangarha.

Added

  • Added ./bin/dev and ./bin/dev-static executables to ease and standardize running the dev server. PR 1491 by ahangarha.

13.2.0 - 2022-12-23

Fixed

  • Fix reactOnRailsPageUnloaded when there is no component on the page. Important for apps using both hotwire and react_on_rails. PR 1498 by NhanHo.
  • Fixing wrong type. The throwIfMissing param of getStore should be optional as it defaults to true. PR 1480 by wouldntsavezion.

Added

13.1.0 - 2022-08-20

Improved

  • Removed addition of mini_racer gem by default. PR 1453 by vtamara and tomdracz.

    Using mini_racer makes most sense when deploying or building in environments that do not have Javascript runtime present. Since react_on_rails requires Node.js, there's no reason to override ExecJS runtime with mini_racer.

    To migrate this change, remove mini_racer gem from your Gemfile and test your app for correct behaviour. You can continue using mini_racer and it will be still picked as the default ExecJS runtime, if present in your app Gemfile.

  • Upgraded the example test app in spec/dummy to React 18. PR 1463 by alexeyr.

  • Added file-system-based automatic bundle generation feature. PR 1455 by pulkitkkr.

Fixed

  • Correctly unmount roots under React 18. PR 1466 by alexeyr.

  • Fixed the You are importing hydrateRoot from "react-dom" [...] You should instead import it from "react-dom/client" warning under React 18 (#1441). PR 1460 by alexeyr.

    In exchange, you may see a warning like this when building using any version of React below 18:

    WARNING in ./node_modules/react-on-rails/node_package/lib/reactHydrateOrRender.js19:25-52
    Module not found: Error: Can't resolve 'react-dom/client' in '/home/runner/work/react_on_rails/react_on_rails/spec/dummy/node_modules/react-on-rails/node_package/lib'
     @ ./node_modules/react-on-rails/node_package/lib/ReactOnRails.js 34:45-78
     @ ./client/app/packs/client-bundle.js 5:0-42 32:0-23 35:0-21 59:0-26
    

    Note: The node_package/lib/ path in these error examples is now packages/react-on-rails/lib/ in the current structure.

    It can be safely suppressed in your Webpack configuration.

13.0.2 - 2022-03-09

Fixed

  • React 16 doesn't support version property, causing problems loading React on Rails. PR 1435 by justin808.

13.0.1 - 2022-02-09

Improved

13.0.0 - 2022-02-08

Breaking

  • Removed webpacker as a dependency. Add gem Shakapacker to your project, and update your package.json to also use shakapacker.

Fixed

  • Proper throwing of exceptions.
  • Default configuration better handles test env.

12.6.0 - 2022-01-22

Added

  • A rendering_props_extension configuration which takes a module with an adjust_props_for_client_side_hydration method, which is used to process props differently for server/client if prerender is set to true. PR 1413 by gscarv13 & judahmeek.

12.5.2 - 2021-12-29

Fixed

  • Usage of config.build_production_command for custom command for production builds fixed. PR 1415 by judahmeek.

12.5.1 - 2021-12-27

Fixed

  • A fatal server rendering error if running an ReactOnRails >=12.4.0 with ReactOnRails Pro <2.4.0. PR 1412 by judahmeek.

12.5.0 - 2021-12-26

Added

  • Support for React 18, including the changed SSR API. PR 1409 by kylemellander.
  • Added Webpack configuration files as part of the generator and updated webpacker to version 6. PR 1404 by gscarv13.
  • Supports Rails 7.

Changed

  • Changed logic of determining the usage of the default rails/webpacker Webpack config or a custom command to only check if the config.build_production_command is defined. PR 1402 by justin808 and gscarv13.
  • Minimum required Ruby is 2.7 to match latest rails/webpacker.

12.4.0 - 2021-09-22

Added

  • ScoutAPM tracing support for server rendering PR 1379 by justin808.

  • Ability to stop React on Rails from modifying or creating the assets:precompile task. PR 1371 by justin808. Thanks to elstgav for the suggestion!

  • Added the ability to have render functions return a promise to be awaited by React on Rails Pro Node Renderer. PR 1380 by judahmeek

12.3.0 - 2021-07-26

Added

  • Ability to use with Turbo (@hotwired/turbo), as Turbolinks gets obsolete. PR 1374 by pgruener and PR 1377 by mdesantis.

    To configure turbo the following option can be set:
    ReactOnRails.setOptions({ turbo: true })

12.2.0 - 2021-03-25

Added

  • Ability to configure server React rendering to throw rather than just logging the error. Useful for
    React on Rails Pro Node rendering PR 1365 by justin808.

12.1.0 - 2021-03-23

Added

Fixed

12.0.4 - 2020-11-14

Fixed

12.0.3 - 2020-09-20

Fixed

12.0.2 - 2020-07-09

Fixed

12.0.1 - 2020-07-09

Fixed

  • Changed invocation of webpacker:clean to use a very large number of versions so it does not accidentally delete the server-bundle.js. PR 1306 by By justin808.

12.0.0 - 2020-07-08

For upgrade instructions, see the upgrading guide.

Major Improvements

  1. React Hooks Support for top level components
  2. Typescript bindings
  3. rails/webpacker "just works" with React on Rails by default.
  4. i18n support for generating a JSON file rather than a JS file.

BREAKING CHANGE

In order to solve the issues regarding React Hooks compatibility, the number of parameters
for functions is used to determine if you have a generator function that will get invoked to
return a React component, or you are registering a functional React component. Alternately, you can
set JavaScript property renderFunction on the function for which you want to return to be
invoked to return the React component. In that case, you won't need to pass any unused params.
PR 1268 by justin808

See docs/guides/upgrading-react-on-rails
for details.

Other Updates

  • react_on_rails fully supports rails/webpacker. The example test app in spec/dummy was recently converted over to use rails/webpacker v4+. It's a good example of how to leverage rails/webpacker's Webpack configuration for server-side rendering.

  • Changed the precompile task to use the rails/webpacker one by default

  • Updated generators to use React hooks

  • Requires the use of rails/webpacker view helpers

  • If the webpacker Webpack config files exist, then React on Rails will not override the default
    assets:precompile set up by rails/webpacker. If you are not using the rails/webpacker setup for Webpack,
    then be sure to remove the JS files inside of config/webpack, like config/webpack/production.js.

  • Removed env_javascript_include_tag and env_stylesheet_link_tag as these are replaced by view helpers
    from rails/webpacker

  • Removal of support for old Rubies and Rails.

  • Removal of config.symlink_non_digested_assets_regex as it's no longer needed with rails/webpacker.
    If any business needs this, we can move the code to a separate gem.

  • Added configuration option same_bundle_for_client_and_server with default false because

    1. Production applications would typically have a server bundle that differs from the client bundle
    2. This change only affects trying to use HMR with react_on_rails with rails/webpacker.

    The previous behavior was to always go to the webpack-dev-server for the server bundle if the
    webpack-dev-server was running and the server bundle was found in the manifest.json.

    If you are using the same bundle for client and server rendering, then set this configuration option
    to true. By justin808.

  • Added support to export locales in JSON format. New option added i18n_output_format which allows to
    specify locales format either JSON or JS. JSON format is now the default.

    Use this config setting to get the old behavior: config.i18n_output_format = 'js'

    PR 1271 by ashgaliyev.

  • Added Typescript definitions to the Node package. By justin808 and judahmeek in PR 1287.

  • Removed restriction to keep the server bundle in the same directory with the client bundles. Rails/webpacker 4 has an advanced cleanup that will remove any files in the directory of other Webpack files. Removing this restriction allows the server bundle to be created in a sibling directory. By justin808.

11.3.0 - 2019-05-24

Added

  • Added method for retrieving any option from render_options PR 1213
    by ashgaliyev.

  • html_options has an option for 'tag' to set the html tag name like this: html_options: { tag: "span" }.
    PR 1208 by tahsin352.

11.2.2 - 2018-12-24

Improved

  • rails_context can more easily be called from controller methods. The mandatory param of server_side has been made optional.

11.2.1 - 2018-12-06

MIGRATION for v11.2

  • If using React on Rails Pro, upgrade react_on_rails_pro to a version >= 1.3.

Improved

  • To support React v16, updated API for manually calling ReactOnRails.render(name, props, domNodeId, hydrate). Added 3rd @param hydrate Pass truthy to update server rendered html. Default is falsey Any truthy values calls hydrate rather than render. PR 1159 by justin808 and coopersamuel.

  • Enabled the use of webpack-dev-server with Server-side rendering. PR 1173 by justin808 and judahmeek.

Changed

  • Changed the default for:

    config.raise_on_prerender_error = Rails.env.development?

    Thus, developers will need to fix server rendering errors before continuing.
    PR 1145 by justin808.

11.2.0 - 2018-12-06

Do not use. Unpublished. Caused by an issue with the release script.

11.1.8 - 2018-10-14

Improved

  • Improved tutorial and support for HMR when using rails/webpacker for Webpack configuration. PR 1156 by 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

11.1.6 - 2018-10-05

Fixed

  • Fix client startup invoking render prematurely, AGAIN. Fix additional cases of client startup failing during interactive readyState". Closes issue #1150. PR 1152 by rakelley.

11.1.5 - 2018-10-03

Fixed

11.1.4 - 2018-09-12

Fixed

11.1.3 - 2018-08-26

Fixed

11.1.2 - 2018-08-18

Fixed

  • Tests now properly exit if the config.build_test_command fails!
  • Source path for project using Webpacker would default to "app/javascript" even if when the node_modules
    directory was set to "client". Fix now makes the configuration of this crystal clear.
  • renamed method RenderOptions.has_random_dom_id? to RenderOptions.random_dom_id? for rubocop rule.
    PR 1133 by justin808

11.1.1 - 2018-08-09

Fixed

11.1.0 - 2018-08-07

Added

  • Add random dom id option. This new global and react_component helper option allows configuring whether or not React on Rails will automatically add a random id to the DOM node ID. PR 1121 by justin808
    • Added configuration option random_dom_id
    • Added method RenderOptions has_random_dom_id?

Fixed

11.0.10 - 2018-07-22

Fixed

  • Much better logging of rendering errors when there are lots of props. Only the a 1,000 chars are logged, and the center is indicated to be truncated. PR 1117 and PR 1118 by justin808.
  • Properly clearing hydrated stores when server rendering. PR 1120 by squadette.

11.0.9 - 2018-06-24

11.0.8 - 2018-06-15

Fixed

  • HashWithIndifferent access for props threw if used for props. PR 1100 by justin808.
  • Test helper for detecting stale bundles did not properly handle the case of a server-bundle.js without a hash.PR 1102 by justin808.
  • Fix test helper determination of stale assets. PR 1093 by justin808.

Changed

  • Document how to manually rehydrate XHR-substituted components on client side. PR 1095 by hchevalier.

11.0.7 - 2018-05-16

Fixed

11.0.6 - 2018-05-15

Changed

  • Even more detailed errors for Honeybadger and Sentry when there's a JSON parse error on server rendering. PR 1086 by justin808.

11.0.5 - 2018-05-11

Changed

11.0.4 - 2018-05-3

Changed

  • Throw if configuration.generated_assets_dir specified, and using webpacker, and if that doesn't match the public_output_path. Otherwise, warn if generated_assets_dir is specified
  • Fix the setup for tests for spec/dummy so they automatically rebuild by correctly setting the source_path in the webpacker.yml
  • Updated documentation for the testing setup.
  • Above in PR 1072 by justin808.
  • react_component_hash has implicit prerender: true because it makes no sense to have react_component_hash not use prerrender. Improved docs on react_component_hash. Also, fixed issue where checking gem existence. PR 1077 by justin808.

11.0.3 - 2018-04-24

Fixed

  • Fixed issue with component script initialization when using react_component_hash. PR 1071 by jblasco3.

11.0.2 - 2018-04-24

Fixed

11.0.1 - 2018-04-23

Added

  • react_component allows logging_on_server specified at the component level. PR 1068 by justin808.

Fixed

11.0.0 - 2018-04-21

MIGRATION for v11

  • Unused server_render_method was removed from the configuration. If you want to use a custom renderer, contact [email protected]. We have a custom node rendering solution in production for egghead.io.
  • Removed ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name. These are part of the performance features of "React on Rails Pro".
  • Removed ENV["TRACE_REACT_ON_RAILS"] usage and replacing it with config.trace.

Enhancements: Better Error Messages, Support for React on Rails Pro

  • Tracing (debugging) options are simplified with a single config.trace setting that defaults to true for development and false otherwise.
  • Calls to setTimeout, setInterval, clearTimeout will now always log some message if config.trace is true. Your JavaScript code should not be calling setTimout when server rendering.
  • Errors raised are of type ReactOnRailsError, so you can see they came from React on Rails for debugging.
  • Removed ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name.
  • No longer logging the railsContext when server logging.
  • Rails.env is provided in the default railsContext, as suggested in issue #697.
    PR 1065 by justin808.

Fixes

  • More exact version checking. We keep the react_on_rails gem and the react-on-rails node package at
    the same exact versions so that we can be sure that the interaction between them is precise.
    This is so that if a bug is detected after some update, it's critical that
    both the gem and the node package get the updates. This change ensures that the package.json specification does not use a
    ~ or ^ as reported in issue #1062. PR 1063 by justin808.
  • Sprockets: Now use the most recent manifest when creating symlinks. See issue #1023. PR 1064 by justin808.

10.1.4 - 2018-04-11

Fixed

  • Changed i18n parsing to convert ruby i18n argument syntax into FormatJS argument syntax. PR 1046 by sepehr500.

  • Fixed an issue where the spec compiler check would fail if the project path contained spaces. PR 1045 by andrewmarkle.

  • Updated the default build_production_command that caused production assets to be built with development settings. PR 1053 by Roman Kushnir.

10.1.3 - 2018-02-28

Fixed

  • Improved error reporting on version mismatches between Javascript and Ruby packages. PR 1025 by theJoeBiz.

10.1.2 - 2018-02-27

Fixed

  • Use ReactDOM.hydrate() for hydrating a SSR component if available. ReactDOM.render() has been deprecated for use on SSR components in React 16 and this addresses the warning. PR 1028 by theJoeBiz.

10.1.1 - 2018-01-26

Fixed

10.1.0 - 2018-01-23

Added

  • Added 2 cache helpers: ReactOnRails::Utils.bundle_file_name(bundle_name) and ReactOnRails::Utils.server_bundle_file_name
    for easy access to the hashed filenames for use in cache keys. PR 1018 by justin808.

Fixed

  • Use Redux component in the generated Redux Hello World example: PR 1006 by lewaabahmad.
  • Fixed Utils.bundle_js_file_path generating the incorrect path for manifest.json in webpacker projects: Issue #1011 by elstgav

10.0.2 - 2017-11-10

Fixed

  • Remove unnecessary dependencies from released NPM package: PR 968 by tricknotes.

10.0.1 - 2017-10-28

Fixed

  • Fixed react_component_hash functionality in cases of prerendering errors: PR 960 by Judahmeek.
  • Fix to add missing dependency to run generator spec individually: PR 962 by tricknotes.
  • Fixes check for i18n_dir in LocalesToJs returning false when i18n_dir was set. PR 899 by hakongit.
  • Fixed mistake in rubocop comments that led to errors when handling exceptions in ReactOnRails::ServerRendering::Exec PR 963 by railsme.
  • Fixed and improved I18n directories checks: PR 967 by railsme

10.0.0 - 2017-10-08

Created

  • Created react_component_hash method for react_helmet support.

Deprecated

  • Deprecated react_component functionality for react_helmet support.
    To clarify, the method itself is not deprecated, only certain functionality which has been moved to react_component_hash
    PR 951 by Judahmeek.

9.0.3 - 2017-09-20

Improved

9.0.2 - 2017-09-10

Fixed

9.0.1 - 2017-09-10

Fixed

9.0.0 - 2017-09-06

Updated React on Rails to depend on rails/webpacker. PR 908 by justin808.

9.0 from 8.x. Upgrade Instructions

Moved to our documentation.

8.0.7 - 2017-08-16

Fixed

  • Fixes generator bug by keeping blank line at top in case existing .gitignore does not end in a newline. #916 by justin808.

8.0.6 - 2017-07-19

Fixed

  • Fixes server rendering when using a CDN. Server rendering would try to fetch a file with the "asset_host". This change updates the webpacker_lite dependency to 2.1.0 which has a new helper pack_path. #901 by justin808. Be sure to update webpacker_lite to 2.1.0.
  • The package.json file created by the generator now creates minified javascript production builds by default. This was done by adding the -p flag to Webpack on the build:production script. #895 by serodriguez68
  • Fixes GitUtils.uncommitted_changes? throwing an error when called in an environment without Git, and allows install generator to be run successfully with --ignore-warnings #878 by jasonblalock.

8.0.5 - 2017-07-04

Fixed

  • Corrects devBuild value for webpack production build from webpackConfigLoader. #877 by chenqingspring.
  • Remove contentBase deprecation warning message. #878 by ened .
  • Removes invalid reference to _railsContext in the generated files. #886 by justin808.
  • All tests run against Rails 5.1.2

Note: 8.0.4 skipped.

8.0.3 - 2017-06-19

Fixed

8.0.2 - 2017-06-04

Fixed

  • Any failure in webpack to build test files quits tests.
  • Fixed a Ruby 2.4 potential crash which could cause a crash due to pathname change in Ruby 2.4.
  • CI Improvements:
    • Switched to yarn link and removed relative path install of react-on-rails
    • Removed testing of Turbolinks 2
    • All tests run against Rails 5.1.1
    • Fixed test failures against Ruby 2.4
  • #862 by justin808

8.0.1 - 2017-05-30

Fixed

8.0.0 - 2017-05-29

  • Generators and full support for webpacker_lite
  • No breaking changes to move to 8.0.0 other than the default for this setting changed to nil. If you depended on the default of this setting and are using the asset pipeline (and not webpacker_lite), then add this to your config/initializers/react_on_rails.rb:
    symlink_non_digested_assets_regex: /\.(png|jpg|jpeg|gif|tiff|woff|ttf|eot|svg|map)/,
    
  • For an example of migration, see: react-webpack-rails-tutorial PR #395
  • For a simple example of the webpacker_lite setup, run the basic generator.

8.0.0-beta.3 - 2017-05-27

Changed

8.0.0-beta.2 - 2017-05-08

Changed

Removed unnecessary values in default paths.yml files for generators. #834 by justin808.

8.0.0-beta.1 - 2017-05-03

Added

Support for WebpackerLite in the generators. #822 by kaizencodes and justin808.

Changed

Breaking change is that the default value of symlink_non_digested_assets_regex has changed from this
old value to nil. This is a breaking change if you didn't have this value set in your
config/initializers/react_on_rails.rb file and you need this because you're using webpack's CSS
features and you have not switched to webpacker lite.

symlink_non_digested_assets_regex: /\.(png|jpg|jpeg|gif|tiff|woff|ttf|eot|svg|map)/,

7.0.4 - 2017-04-27

  • Return empty json when nil in json_safe_and_pretty #824 by dzirtusss

7.0.3 - 2017-04-27

Same as 7.0.1.

7.0.2 - 2017-04-27

Accidental release of beta gem here

7.0.1 - 2017-04-27

Fixed

  • Fix to handle nil values in json_safe_and_pretty #823 by dzirtusss

7.0.0 - 2017-04-25

Changed

  • Any version differences in gem and node package for React on Rails throw an error #821 by justin808

Fixed

  • Fixes serious performance regression when using String props for rendering. #821 by justin808

6.10.1 - 2017-04-23

Fixed

6.10.0 - 2017-04-13

Added

  • Add an ability to return multiple HTML strings in a Hash as a result of react_component method call. Allows to build <head> contents with React Helmet. #800 by udovenko.

Fixed

  • Fix PropTypes, createClass deprecation warnings for React 15.5.x. #804 by udovenko .

6.9.3 - 2017-04-03

Fixed

  • Removed call of to_json on strings when formatting props. #791 by justin808.

6.9.2 - 2017-04-02

Changed

  • Update version_checker.rb to logger.error rather than logger.warn for gem/npm version mismatch. #788 by justin808.

Fixed

  • Remove pretty formatting of JSON in development. #789 by justin808
  • Clear hydrated stores with each server rendered block. #785 by udovenko

6.9.1 - 2017-03-30

Fixed

  • Fixes Crash in Development for String Props. #784 by justin808.

6.9.0 - 2017-03-29

Fixed

  • Fixed error in the release script. #767 by isolo.

Changed

Added

  • Add option to specify i18n_yml_dir in order to include only subset of locale files when generating translations.js & default.js for react-intl.
    #777 by danijel.

6.8.2 - 2017-03-24

Fixed

  • Change webpack output path to absolute and update webpack to version ^2.3.1. #771 by cheremukhin23.

6.8.1 - 2017-03-21

Fixed

  • Fixed error "The node you're attempting to unmount was rendered by another copy of React." #706 when navigating to cached page using Turbolinks #763 by szyablitsky.

6.8.0 - 2017-03-06

Added

  • Converted to Webpack v2 for generators, tests, and all example code. #742 by justin808.

6.7.2 - 2017-03-05

Improved

  • Improve i18n Integration with a better error message if the value of the i18n directory is invalid. #748 by justin808.

6.7.1 - 2017-02-28

No changes other than a test fix.

6.7.0 - 2017-02-28

IMPORTANT

  • If you installed 6.6.0, you will need to comment out the line matching i18n_dir unless you are using this feature. 6.7.1 will give you an error like:
Errno::ENOENT: No such file or directory @ rb_sysopen - /tmp/build_1444a5bb9dd16ddb2561c7aff40f0fc7/my-app-816d31e9896edd90cecf1402acd002c724269333/client/app/libs/i18n/translations.js

Commenting out this line addresses the issue:

config.i18n_dir = Rails.root.join("client", "app", "libs", "i18n")

Added

  • Allow using rake task to generate javascript locale files. The test helper automatically creates the localization files when needed. #717 by JasonYCHuang.

Fixed

6.6.0 - 2017-02-18

Added

6.5.1 - 2017-02-11

Fixed

6.5.0 - 2017-01-31

Added

  • Allow generator function to return Object with property renderedHtml (already could return Object with props redirectLocation, error) rather than a React component or a function that returns a React component. One reason to use a generator function is that sometimes in server rendering, specifically with React Router v4, you need to return the result of calling ReactDOMServer.renderToString(element). #689 by justin808.

Fixed

6.4.2 - 2017-01-17

Fixed

  • Added OS detection for install generator, system call for Windows and unit-tests for it. #666 by GeorgeGorbanev.

6.4.1 - 2017-1-17

No changes.

6.4.0 - 2017-1-12

Possible Breaking Change

  • Since foreman is no longer a dependency of the React on Rails gem, please run gem install foreman. If you are using rvm, you may wish to run rvm @global do gem install foreman to install foreman for all your gemsets.

Fixed

  • Removed foreman as a dependency. #678 by x2es.

Added

  • Automatically generate i18n javascript files for react-intl when the serve starts up. #642 by JasonYCHuang.

6.3.5 - 2017-1-6

Fixed

  • The Redux generator now creates a HelloWorld component that uses redux rather than local state. #669 by justin808.

6.3.4 - 2016-12-25

Fixed
  • Disable Turbolinks support when not supported. #650 by ka2n.

6.3.3 - 2016-12-25

Fixed
  • By using the hook on turbolinks:before-visit to unmount the components, we can ensure that components are unmounted even when Turbolinks cache is disabled. Previously, we used turbolinks:before-cache event hook. #644 by volkanunsal.
  • Added support for Ruby 2.0 #651 by bbonamin.

6.3.2 - 2016-12-5

Fixed
  • The react_component method was raising a NameError when ReactOnRailsHelper was included in a plain object. #636 by jtibbertsma.
  • "Node parse error" for node server rendering. #641 by alleycat-at-git and rocLv
  • Better error handling when the react-on-rails node package entry is missing.#602 by benjiwheeler.

6.3.1 - 2016-11-30

Changed
  • Improved generator post-install help messages. #631 by justin808.

6.3.0 - 2016-11-30

Changed
  • Modified register API to allow registration of renderers, allowing a user to manually render their app to the DOM. This allows for code splitting and deferred loading. #581 by jtibbertsma.

  • Updated Basic Generator & Linters. Examples are simpler. #624 by Judahmeek.

  • Slight improvement to the 'no hydrated stores' error. #605 by cookiefission.

  • Don't assume ActionMailer is available. #608 by tuzz.

6.2.1 - 2016-11-19

  • Removed unnecessary passing of context in the HelloWorld Container example and basic generator. #612 by justin808

  • Turbolinks 5 bugfix to use before-cache, not before-render. #611 by volkanunsal.

6.2.0 - 2016-11-19

Changed
  • Updated the generator templates to reflect current best practices, especially for the Redux version. #584 by nostophilia.

6.1.2 - 2016-10-24

Fixed
  • Added compatibility with older manifest.yml files produced by Rails 3 Sprockets when symlinking digested assets during precompilation #566 by etripier.

6.1.1 - 2016-09-09

Fixed
  • React on Rails was incorrectly failing to create symlinks when a file existed in the location for the new symlink. #491 by robwise and justin808.

6.1.0 - 2016-08-21

Added
  • Node option for installer added as alternative for server rendering #469 by jbhatab.
  • Server rendering now supports contexts outside of browser rendering, such as ActionMailer templates #486 by eacaps.
  • Added authenticityToken() and authenticityHeaders() javascript helpers for easier use when working with CSRF protection tag generated by Rails #517 by dzirtusss.
  • Updated JavaScript error handling on the client side. Errors in client rendering now pass through to the browser #521 by dzirtusss.
Fixed
  • React on Rails now correctly parses single-digit version strings from package.json #491 by samphilipd .
  • Fixed assets symlinking to correctly use filenames with spaces. Beginning in #510, ending in #513 by dzirtusss.
  • Check encoding of request's original URL and force it to UTF-8 #527 by lucke84

6.0.5 - 2016-07-11

Added
  • Added better error messages to avoid issues with shared Redux stores #470 by justin808.

6.0.4 - 2016-06-13

Fixed
  • Added a polyfill for clearTimeout which is used by babel-polyfill #451 by martyphee

6.0.3 - 2016-06-07

Fixed

6.0.2 - 2016-06-06

Fixed
  • Fix collisions in ids of DOM nodes generated by react_component by indexing in using a UUID rather than an auto-increment value. This means that it should be overridden using the id parameter of react_component if one wants to generate a predictable id (e.g. for testing purpose). See Issue #437. Fixed in #438 by Michael Baudino.

6.0.1 - 2016-05-27

Fixed

6.0.0 - 2016-05-25

Breaking Changes
  • Added automatic compilation of assets at precompile is now done by ReactOnRails. Thus, you don't need to provide your own assets.rake file that does the precompilation.
    #398 by robwise, jbhatab, and justin808.

  • Migration to v6

    • Do not run the generator again if you've already run it.

    • See shakacode/react-webpack-rails-tutorial/pull/287 for an example of upgrading from v5.

    • To configure the asset compilation you can either

      1. Specify a config/react_on_rails setting for build_production_command to be nil to turn this feature off.
      2. Specify the script command you want to run to build your production assets, and remove your assets.rake file.
    • If you are using the ReactOnRails test helper, then you will need to add the 'config.npm_build_test_command' to your config to tell react_on_rails what command to run when you run rspec.

  • See shakacode/react-webpack-rails-tutorial #287 for an upgrade example. The PR has a few comments on the upgrade.

Here is the addition to the generated config file:

  # This configures the script to run to build the production assets by webpack. Set this to nil
  # if you don't want react_on_rails building this file for you.
  config.build_production_command = "npm run build:production"

  # If you are using the ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
  # with rspec then this controls what npm command is run
  # to automatically refresh your webpack assets on every test run.
  config.npm_build_test_command = "npm run build:test"
Fixed
  • Fixed errors when server rendered props contain \u2028 or \u2029 characters #375 by mariusandra
  • Fixed "too early unmount" which caused problems with Turbolinks 5 not updating the screen #425 by szyablitsky
Added
  • Experimental ability to use node.js process for server rendering. See #380 by alleycat-at-git.
  • Non-digested version of assets in public folder #413 by alleycat-at-git.
  • Cache client/node_modules directory to prevent Heroku from reinstalling all modules from scratch #324 by modosc.
  • ReactOnRails.reactOnRailsPageLoaded() is exposed in case one needs to call this manually and information on async script loading added. See #315 by SqueezedLight.
Changed
  • #398 by robwise, jbhatab, and justin808 contains:
    • Only one webpack config is generated for server and client config. Package.json files were changed to reflect this.
    • Added npm_build_test_command to allow developers to change what npm command is automatically run from rspec.
  • Replace URI with Addressable gem. See #405 by lucke84
Removed
  • #398 by robwise, jbhatab, and justin808 contains:
    • Server rendering is no longer an option in the generator and is always accessible.
    • Removed lodash, jquery, and loggerMiddleware from the generated code.
    • Removed webpack watch check for test helper automatic compilation.

5.2.0 - 2016-04-08

Added
  • Support for React 15.0 to react_on_rails. See #379 by brucek.
  • Support for Node.js server side rendering. See #380 by alleycat and doc
Removed
  • Generator removals to simplify installer. See #364 by jbhatab.
    • Removed options for heroku, boostrap, and the linters from generator.
    • Removed install for the Webpack Dev Server, as we can now do hot reloading with Rails, so the complexity of this feature is not justified. Nevertheless, the setup of React on Rails still supports this setup, just not with the generator.
    • Documentation added for removed installer options.

5.1.1 - 2016-04-04

Fixed
  • Security Fixes: Address failure to sanitize console messages when server rendering and displaying in the browser console. See #366 and #370 by justin808
Added
  • railsContext includes the port number and a boolean if the code is being run on the server or client.

5.1.0 - 2016-04-03

Added

All 5.1.0 changes can be found in #362 by justin808.

  • Generator enhancements
    • Generator adds line to spec/rails_helper.rb so that running specs will ensure assets are compiled.
    • Other small changes to the generator including adding necessary npm scripts to allow React on Rails to build assets.
    • Npm modules updated for generator.
    • Added babel-runtime in to the client/package.json created.
  • Server rendering
    • Added more diagnostics for server rendering.
    • Calls to setTimeout and setInterval are not logged for server rendering unless env TRACE_REACT_ON_RAILS is set to YES.
  • Updated all project npm dependencies to latest.
  • Update to node 5.10.0 for CI.
  • Added babel-runtime as a peer dependency for the npm module.

5.0.0 - 2016-04-01

Added
  • Added railsContext, an object which gets passed always as the second parameter to both React component and Redux store generator functions, both for server and client rendering. This provides data like the current locale, the pathname, etc. The data values are customizable by a new configuration called rendering_extension where you can create a module with a method called rendering_extension. This allows you to add additional values to the Rails Context. Implement one static method called custom_context(view_context) and return a Hash. See #345 by justin808
Changed
  • Previously, you could pass arbitrary additional HTML attributes to react_component. Now, you need to pass them in as a named parameter html_options to react_component.
Breaking Changes
  • You must provide named attributes, including props for view helper react_component. See this commit for an example migration used for reactrails.com.

4.0.3 - 2016-03-17

Fixed
  • ReactOnRailsHelper#react_component: Invalid deprecation message when called with only one parameter, the component name.

4.0.2 - 2016-03-17

Fixed
  • ReactOnRails::Controller#redux_store: 2nd parameter changed to a named parameter props for consistency.

4.0.1 - 2016-03-16

Fixed
  • Switched to heroku buildpacks:set syntax rather than using a .buildpacks file, which is deprecated. See #319 by esauter5. Includes both generator and doc updates.

4.0.0 - 2016-03-14

Added
  • react_on_rails/spec/dummy is a full sample app of React on Rails techniques including the hot reloading of assets from Rails!
  • Added helpers env_stylesheet_link_tag and env_javascript_include_tag to support hot reloading Rails. See the README.md for more details and see the example application in spec/dummy. Also see how this is used in the tutorial: application.html.erb
  • Added optional parameter for ReactOnRails.getStore(name, throwIfMissing = true) so that you can check if a store is defined easily.
  • Added controller module ReactOnRails::Controller. Adds method redux_store to set up Redux stores in the view.
  • Added option defer: true for view helper redux_store. This allows the view helper to specify the props for store hydration, yet still render the props at the bottom of the view.
  • Added view helper redux_store_hydration_data to render the props on the application's layout, near the bottom. This allows for the client hydration data to be parsed after the server rendering, which may result in a faster load time.
  • The checker for outdated bundles before running tests will two configuration options: generated_assets_dir and webpack_generated_files.
  • Better support for Turbolinks 5!
  • Fixed generator check of uncommitted code for foreign languages. See #303 by nmatyukov.
  • Added several parameters used for ensuring webpack assets are built for running tests:
    • config.generated_assets_dir: Directory where your generated webpack assets go. You can have only one directory for this.
    • config.webpack_generated_files: List of files that will get created in the generated_assets_dir. The test runner helper will ensure these generated files are newer than any of the files in the client directory.
Changed
  • Generator default for webpack generated assets is now app/assets/webpack as we use this for both JavaScript and CSS generated assets.
Fixed
  • The test runner "assets up to date checker" is greatly improved.
  • Lots of doc updates!
  • Improved the spec/dummy sample app so that it supports CSS modules, hot reloading, etc, and it can server as a template for a new ReactOnRails installation.
Breaking Changes
  • Deprecated calling redux_store(store_name, props). The API has changed. Use redux_store(store_name, props: props, defer: false) A new option called defer allows the rendering of store hydration at the bottom of the your layout. Place redux_store_hydration_data on your layout.
  • config.server_bundle_js_file has changed. The default value is now blank, meaning no server rendering. Addtionally, if you specify the file name, you should not include the path, as that should be specified in the config.generated_assets_dir.
  • config.generated_assets_dirs has been renamed to config.generated_assets_dir (singular) and it only takes one directory.

3.0.6 - 2016-03-01

Fixed
  • Improved errors when registered store is not found. See #301 by justin808.

3.0.5 - 2016-02-26

Fixed
  • Fixed error in linters rake file for generator. See #299 by mpugach.

3.0.4 - 2016-02-25

Fixed
  • Updated CHANGELOG.md to include contributors for each PR.
  • Fixed config.server_bundle_js file value in generator to match generator setting of server rendering. See #295 by aaronvb.

3.0.3 - 2016-02-21

Fixed
  • Cleaned up code in spec/dummy to latest React and Redux APIs. See #282.
  • Update generator messages with helpful information. See #279.
  • Other small generated comment fixes and doc fixes.

3.0.2 - 2016-02-15

Fixed
  • Fixed missing information in the helpful message after running the base install generator regarding how to run the node server with hot reloading support.

3.0.1 - 2016-02-15

Fixed
  • Fixed several jscs linter issues.

3.0.0 - 2016-02-15

Fixed
  • Fix Bootstrap Sass Append to Gemfile, missing new line. #262.
Added
  • Added helper redux_store and associated JavaScript APIs that allow multiple React components to use the same store. Thus, you initialize the store, with props, separately from the components.
  • Added forman to gemspec in case new dev does not have it globally installed. #248.
  • Support for Turbolinks 5! #270.
  • Added better error messages for ReactOnRails.register(). #273.
Breaking Change
  • Calls to react_component should use a named argument of props. For example, change this:

    <%= react_component("ReduxSharedStoreApp", {}, prerender: false, trace: true) %>

    to

    <%= react_component("ReduxSharedStoreApp", props: {}, prerender: false, trace: true) %>

    You'll get a deprecation message to change this.

  • Renamed ReactOnRails.configure_rspec_to_compile_assets to ReactOnRails::TestHelper.configure_rspec_to_compile_assets. The code has also been optimized to check for whether or not the compiled webpack bundles are up to date or not and will not run if not necessary. If you are using non-standard directories for your generated webpack assets (app/assets/javascripts/generated and app/assets/stylesheets/generated) or have additional directories you wish the helper to check, you need to update your ReactOnRails configuration accordingly. See documentation for how to do this. #253.

  • You have to call ReactOnRails.register to register React components. This was deprecated in v2. #273.

Migration Steps v2 to v3
RSpec.configure do |config|
  # Ensure that if we are running js tests, we are using latest webpack assets
  ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)

2.3.0 - 2016-02-01

Added
  • Added polyfills for setInterval and setTimeout in case other libraries expect these to exist.
  • Added much improved debugging for errors in the server JavaScript webpack file.
  • See #244 for these improvements.

2.2.0 - 2016-01-29

Added
  • New JavaScript API for debugging TurboLinks issues. Be sure to see turbolinks docs. ReactOnRails.setOptions({ traceTurbolinks: true });. Removed the file debug_turbolinks added in 2.1.1. See #243.

2.1.1 - 2016-01-28

Fixed
  • Fixed regression where apps that were not using Turbolinks would not render components on page load.
Added
  • ReactOnRails.render returns a virtualDomElement Reference to your React component's backing instance. See #234.
  • debug_turbolinks helper for debugging turbolinks issues. See turbolinks.
  • Enhanced regression testing for non-turbolinks apps. Runs all tests for dummy app with turbolinks both disabled and enabled.

2.1.0 - 2016-01-26

Added
  • Added EnsureAssetsCompiled feature so that you do not accidentally run tests without properly compiling the JavaScript bundles. Add a line to your rails_helper.rb file to check that the latest Webpack bundles have been generated prior to running tests that may depend on your client-side code. See docs for more detailed instructions. #222
  • Added migration guide for migrating from React-Rails. #219
  • Added React on Rails Doctrine to docs. Discusses the project's motivations, conventions, and principles. #220
  • Added ability to skip display:none style in the generated content tag for a component. Some developers may want to disable inline styles for security reasons. See the skip_display_none configuration option. #218
Changed
  • Changed message when running the dev (a.k.a. "express" server). #227
Fixed
  • Fixed handling of Turbolinks. Code was checking that Turbolinks was installed when it was not yet because some setups load Turbolinks after the bundles. The changes to the code will check if Turbolinks is installed after the page loaded event fires. Code was also added to allow easy debugging of Turbolinks, which should be useful when v5 of Turbolinks is released shortly. Details of how to configure Turbolinks with troubleshooting were added to docs directory. #221
  • Fixed issue with already initialized constant warning appearing when starting a Rails server #226
  • Fixed to make backwards compatible with Ruby v2.0 and updated all Ruby and Node dependencies.

2.0.2

  • Added better messages after generator runs. #210

2.0.1

  • Fixed bug with version matching between gem and npm package.

2.0.0

  • Move JavaScript part of react_on_rails to npm package 'react-on-rails'.
  • Converted JavaScript code to ES6! with tests!
  • No global namespace pollution. ReactOnRails is the only global added.
  • New API. Instead of placing React components on the global namespace, you instead call ReactOnRails.register, passing an object where keys are the names of your components:
import ReactOnRails from 'react-on-rails';
ReactOnRails.register({name: component});

Best done with Object destructing:

  import ReactOnRails from 'react-on-rails';
  ReactOnRails.register(
    {
      Component1,
      Component2
    }
  );

Previously, you used

window.Component1 = Component1;
window.Component2 = Component2;

This would pollute the global namespace. See details in the README.md for more information.

  • Your jade template for the WebpackDevServer setup should use the new API:
  ReactOnRails.render(componentName, props, domNodeId);

such as:

  ReactOnRails.render("HelloWorldApp", {name: "Stranger"}, 'app');
Migration Steps v1 to v2

Example of upgrading

  1. Update the react_on_rails gem.
  2. Remove //= require react_on_rails from any files such as app/assets/javascripts/application.js. This file comes from npm now.
  3. Search you app for 'generator_function' and remove lines in layouts and rb files that contain it. Determination of a generator function is handled automatically.
  4. Find your files where you registered client and server globals, and use the new ReactOnRails.register syntax. Optionally rename the files clientRegistration.jsx and serverRegistration.jsx rather than Globals.
  5. Update your index.jade to use the new API ReactOnRails.render("MyApp", !{props}, 'app');
  6. Update your webpack files per the example commit. Remove globally exposing React and ReactDom, as well as their inclusion in the entry section. These are automatically included now.
  7. Run cd client && npm i --save react-on-rails to get react-on-rails into your client/package.json.
  8. You should also update any other dependencies if possible to match up with the react-webpack-rails-tutorial. This includes updating to Babel 6.
  9. If you want to stick with Babel 5 for a bit, see Issue #238.

1.2.2

Fixed
  • Missing Lodash from generated package.json #175
  • Rails 3.2 could not run generators #182
  • Better placement of jquery_ujs dependency commit b168abd5
  • Add more detailed description when adding --help option to generator commit a9b7d47d
  • Lots of better docs.

1.2.0

Added
  • Support --skip-bootstrap or -b option for generator.
  • Create examples tasks to test generated example apps.
Fixed
  • Fix non-server rendering configuration issues.
  • Fix application.js incorrect overwritten issue.
  • Fix Gemfile dependencies.
  • Fix several generator issues.
Removed
  • Removed templates/client folder.

1.1.1 - 2015-11-28

Added
  • Support for React Router.
  • Error and redirect handling.
  • Turbolinks support.
Fixed
  • Fix several generator-related issues.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

PR Review: Fix 2549 - Clean stale webpack config on --rspack install

The approach is well-designed overall: conservative deletion (only removes known stock files), content-matching for safety, caching rendered templates, and a clear warning when custom files are present. However, there is a critical logic bug that will cause the legacy generateWebpackConfigs.js test to fail, plus a few smaller issues worth addressing.

CRITICAL BUG: generateWebpackConfigs.js is never removable

In removable_webpack_entry? (around line 321 of base_generator.rb), generateWebpackConfigs.js is grouped with webpack.config.js in the case/when clause and compared against the webpack.config.js.tt template and the standard Shakapacker configs. But the content of generateWebpackConfigs.js (the serverClientOrBoth pattern from legacy RoR versions) looks nothing like webpack.config.js. Neither comparison will ever be true, so the method returns false, making the file permanently non-removable.

This means the test removes legacy generateWebpackConfigs.js along with stale config/webpack directory will fail: generateWebpackConfigs.js lands in non_removable_entries, the directory is preserved, and the assertion expect(File).not_to exist(destination_root + config/webpack) fails.

Fix: Map generateWebpackConfigs.js to ServerClientOrBoth.js.tt in MANAGED_WEBPACK_FILE_TEMPLATES (it is the legacy name for the same content), then let the else branch in removable_webpack_entry? handle the content check:

MANAGED_WEBPACK_FILE_TEMPLATES = {
  ...
  ServerClientOrBoth.js     => base/base/config/webpack/ServerClientOrBoth.js.tt,
  generateWebpackConfigs.js => base/base/config/webpack/ServerClientOrBoth.js.tt,
}.freeze

REMOVABLE_WEBPACK_FILES = (MANAGED_WEBPACK_FILE_TEMPLATES.keys + %w[webpack.config.js]).freeze

MINOR: dotfiles in config/webpack are silently deleted

The non-removable check excludes dotfiles, which avoids false positives. But remove_dir deletes the entire directory including dotfiles like .gitkeep without mentioning them. A user who added a .gitkeep to track the directory in git would lose it silently. Consider warning about dotfiles present, or including them in the non-removable entries check.

MINOR: raise in before(:all) for precondition assertion

Using raise inside before(:all) causes every example in that context to report an unexpected error rather than a clear setup failure. Prefer moving the precondition check into its own it block or a helper so failures produce an actionable RSpec message.

MINOR: Full generator context exposed via binding in ERB

In rendered_template_for_cleanup, .result(binding) passes the generators entire method context into the ERB template. This is intentional (templates call use_pro?, use_rsc?, etc.) and not a security issue since templates are source-controlled, but a typo in a template that happens to be valid Ruby will silently evaluate rather than raising. Worth documenting or using a tighter binding if templates expand in the future.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

Overall this is a well-structured solution. The conservative approach (preserve on any doubt, warn rather than delete) is the right default for a generator touching user files. The new specs cover the main paths well. A few things worth addressing:

1. Dotfile-only directories are silently skipped

Dir.children returns dotfiles, but the code immediately rejects entries starting with . and returns early if the resulting list is empty. A config/webpack/ directory containing only .gitkeep (common in Rails repos) would hit entries.empty? and produce no output — no cleanup, no warning. Since the intent is to communicate clearly about what happened, a say_status for this case would improve UX.

2. remove_dir uses a relative path while the guard uses an absolute path

stale_webpack_config_dir returns File.join(destination_root, "config/webpack") (absolute), but remove_dir("config/webpack", ...) uses a relative path. Thor resolves generator paths against destination_root so it works correctly, but the inconsistency is a subtle trap for future maintainers. Prefer one style throughout.

3. Template rendering is options-dependent — not tested for the --pro / --rsc case

rendered_template_for_cleanup renders templates using the current run's use_pro?/use_rsc? options, not the options active when the files were originally generated. A user who installed with --pro but now runs --rspack alone will get a warning instead of cleanup, even with stock-generated files. The inline comment acknowledges this is intentional, but there is no spec for it, so the behaviour could regress silently.

4. raise in before(:all) is a fragile setup guard

Using raise inside before(:all) to assert pre-conditions causes confusing RSpec output (an exception in a hook rather than a normal example failure). A dedicated it example asserting the pre-condition would produce clearer failure messages.

Minor nit: MANAGED_WEBPACK_FILE_TEMPLATES.fetch(entry, nil) can be simplified to MANAGED_WEBPACK_FILE_TEMPLATES[entry] since Hash#[] already returns nil for missing keys.

Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb
Comment thread react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/base_generator.rb Outdated
Comment on lines +77 to +91
def add_documentation_reference(*args)
generator.__send__(:add_documentation_reference, *args)
end

def use_pro?
generator.__send__(:use_pro?)
end

def use_rsc?
generator.__send__(:use_rsc?)
end

def shakapacker_version_9_or_higher?
generator.__send__(:shakapacker_version_9_or_higher?)
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using __send__ to forward to private generator methods works, and failures are caught by the StandardError rescue in rendered_template_for_cleanup (treating the file as non-removable — safe). However, if any of these private methods are later renamed, the breakage is silent: the cleanup silently becomes maximally conservative without any indication why. A test that exercises the happy-path ERB rendering path (not just the failure sentinel) would catch rename-regressions earlier. Alternatively, a short comment cross-referencing the rescue contract here would help future maintainers understand the intentional coupling.

Comment on lines +541 to +543
def stale_webpack_config_dir
File.join(destination_root, "config/webpack")
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string "config/webpack" is hardcoded in two places: here as the full-path base, and as the local webpack_config_relative_dir in cleanup_stale_webpack_config_dir_for_rspack. If the path ever needs to change, both must be updated in sync. Consider deriving one from the other:

Suggested change
def stale_webpack_config_dir
File.join(destination_root, "config/webpack")
end
def stale_webpack_config_dir
File.join(destination_root, stale_webpack_config_relative_dir)
end
def stale_webpack_config_relative_dir
"config/webpack"
end

Then cleanup_stale_webpack_config_dir_for_rspack can use webpack_config_relative_dir = stale_webpack_config_relative_dir and avoid the duplication.

Comment on lines +508 to +510
def rendered_template_for_cleanup(template_path)
@rendered_template_cache ||= {}
@rendered_template_cache[template_path] ||= begin
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ||= pattern works correctly here because TEMPLATE_RENDER_FAILED is a truthy Object instance, so the block is never re-executed once it has been cached. However, there is one subtle gap: if File.read returns an empty string (a zero-byte template), @rendered_template_cache[template_path] would store "". In Ruby "" is truthy, so ||= would not re-run — this is correct. But content_matches_template?("", "") would return true, meaning a zero-byte file would be treated as removable. This edge case is benign for real templates, but worth a brief note if this cache is ever reused for other template types.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 13, 2026

Review Summary

This is a well-designed, conservative implementation of the stale webpack config cleanup. The overall approach - only deleting files that exactly match known generated content, warning and preserving everything else - is the right call for a destructive generator step. The test coverage is thorough and the intent is clearly documented.

Strengths

  • Conservative by design: symlinks, dotfiles, subdirectories, comment-only edits, and template-render failures all prevent deletion. Good default.
  • TEMPLATE_RENDER_FAILED sentinel: correctly used with identity comparison (.equal?) and properly cached. The intentional caching note in the comment is helpful.
  • Template coverage test in base_generator_spec.rb: the Dir.glob check that ensures MANAGED_WEBPACK_FILE_TEMPLATES stays in sync with on-disk templates is an excellent regression guard.
  • strip_comments: keyword on standard_shakapacker_config?: cleanly separates the historical comment-insensitive replacement path from the new conservative cleanup path. The documentation comment explaining why the default changed is appreciated.
  • Error handling breadth: Errno::EACCES, ELOOP, EISDIR, ENOTDIR are all covered in the right places.

Issues / Suggestions

See inline comments, summarized here:

  1. Double file I/O (lines 350-351): non_removable_webpack_entries and removable_webpack_entries each call removable_webpack_entry? (which reads files) for every entry. Using partition would do a single pass and also eliminate the narrow TOCTOU window between the two separate iterations.

  2. __send__ to private methods in TemplateRenderContext (lines 77-91): Silent failures are safe (caught by StandardError rescue), but a rename would silently make cleanup maximally conservative with no diagnostic. A cross-reference comment or a rendering happy-path test would help.

  3. Hardcoded path duplication (lines 541-543): "config/webpack" appears both in stale_webpack_config_dir and as a local variable in the caller. Extracting a stale_webpack_config_relative_dir helper would keep them in sync automatically.

  4. Empty-string template edge case (lines 508-510): Purely theoretical for real templates, but worth a brief note that ||= caching of "" (zero-byte template) would compare equal to a zero-byte on-disk file.

None of these are blockers - the logic is sound and the implementation is well-thought-out.

@justin808 justin808 merged commit 7952f76 into master Mar 15, 2026
33 of 34 checks passed
@justin808 justin808 deleted the jg-codex/fix-2549-rspack-cleanup branch March 15, 2026 01:10
justin808 added a commit that referenced this pull request Mar 15, 2026
Add PR #2597 (clean stale webpack config on --rspack install) to changelog
and stamp 16.4.0.rc.10 version header.

Also update the /update-changelog skill to:
- Auto-commit, push, and open a PR after stamping a version
- Ask for user confirmation on ambiguous version bumps

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@justin808 justin808 mentioned this pull request Mar 15, 2026
2 tasks
ihabadham added a commit that referenced this pull request Mar 15, 2026
Master's PR #2597 added strip_comments: keyword to
standard_shakapacker_config?. The copy_webpack_main_config call site
passes strip_comments: true, so test stubs must match.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
justin808 added a commit that referenced this pull request Mar 16, 2026
## Summary

- **Add PR #2597** (clean stale webpack config on `--rspack` install) to
changelog under `#### Fixed`
- **Stamp `16.4.0.rc.10`** version header with today's date
- **Improve `/update-changelog` skill**: auto-commit/push/PR after
stamping, ask for confirmation on ambiguous version bumps

## Test plan

- [ ] Verify CHANGELOG.md formatting and version links are correct
- [ ] Verify `/update-changelog` skill reads correctly for future
invocations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only updates to the changelog and the Claude
`/update-changelog` command instructions; no runtime code paths changed.
> 
> **Overview**
> Stamps a new `### [16.4.0.rc.10] - 2026-03-14` section in
`CHANGELOG.md`, folding in the `--rspack` stale `config/webpack/`
cleanup fix and updating the compare links.
> 
> Updates the `/update-changelog` command docs to (1) require explicit
user confirmation when the suggested bump type is ambiguous and (2)
switch release/rc/beta mode guidance from manual “commit/push” steps to
**automatically creating a branch, committing, pushing, and opening a
PR** after stamping.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
596cc76. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Ruby 3.4 heredoc compatibility, pnpm workspace setup guard, SSR error
serialization, CSS module SSR behavior, stale webpack cleanup, and
private path handling on fresh installs.

* **New Features**
* Explicit version stamping for changelogs (supports .rc/.beta), clearer
prerelease/RC/Beta flows, automated changelog PR creation, and
consolidation of duplicate changelog headings.

* **Tests**
  * Added/updated tests to verify changelog consolidation and ordering.

* **Chores**
* Improved bump confirmation messaging and expanded workflow
documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
AbanoubGhadban pushed a commit that referenced this pull request Mar 16, 2026
Master's PR #2597 added strip_comments: keyword to
standard_shakapacker_config?. The copy_webpack_main_config call site
passes strip_comments: true, so test stubs must match.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
justin808 added a commit that referenced this pull request Mar 30, 2026
## Summary
- remove stale  files when running 
- only remove when files are known stock/generated webpack config files
- preserve directory and warn when custom files are present
- add generator specs for both cleanup and preservation paths

Fixes #2549

## Testing
- Inspecting 2 files
..

2 files inspected, no offenses detected
- Run options: include {focus: true, locations:
{"./react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb"
=> [559, 632]}}
..

Finished in 44.88 seconds (files took 1.28 seconds to load)
2 examples, 0 failures

Run options: --seed 2821

# Running:



Finished in 0.000584s, 0.0000 runs/s, 0.0000 assertions/s.

0 runs, 0 assertions, 0 failures, 0 errors, 0 skips

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because the generator now conditionally deletes
`config/webpack/` based on file/content matching, which could remove
expected files if detection is wrong, though it attempts to preserve
custom/unknown files and warns instead.
> 
> **Overview**
> Fixes `--rspack` installs leaving behind stale `config/webpack/` by
adding a cleanup step that **removes the directory only when it contains
known stock/generated webpack configs**; otherwise it preserves the
directory and emits a warning listing custom/unknown files.
> 
> The generator now tracks managed webpack template files and renders
templates via `ERB` to verify file contents before deletion, and specs
add coverage for both the removal path and the preservation path when
custom webpack files are present.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
474a075. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Conservative, automatic cleanup of stale Webpack config when switching
to Rspack, while preserving user-customized files and using
template-aware comparisons to avoid removing modified configs.
* Automatic generation or replacement of Rspack configuration where
appropriate.

* **Tests**
* Added comprehensive tests validating cleanup, preservation,
legacy-file removal, and Rspack generation across transition scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
justin808 added a commit that referenced this pull request Mar 30, 2026
## Summary

- **Add PR #2597** (clean stale webpack config on `--rspack` install) to
changelog under `#### Fixed`
- **Stamp `16.4.0.rc.10`** version header with today's date
- **Improve `/update-changelog` skill**: auto-commit/push/PR after
stamping, ask for confirmation on ambiguous version bumps

## Test plan

- [ ] Verify CHANGELOG.md formatting and version links are correct
- [ ] Verify `/update-changelog` skill reads correctly for future
invocations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only updates to the changelog and the Claude
`/update-changelog` command instructions; no runtime code paths changed.
> 
> **Overview**
> Stamps a new `### [16.4.0.rc.10] - 2026-03-14` section in
`CHANGELOG.md`, folding in the `--rspack` stale `config/webpack/`
cleanup fix and updating the compare links.
> 
> Updates the `/update-changelog` command docs to (1) require explicit
user confirmation when the suggested bump type is ambiguous and (2)
switch release/rc/beta mode guidance from manual “commit/push” steps to
**automatically creating a branch, committing, pushing, and opening a
PR** after stamping.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
596cc76. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Ruby 3.4 heredoc compatibility, pnpm workspace setup guard, SSR error
serialization, CSS module SSR behavior, stale webpack cleanup, and
private path handling on fresh installs.

* **New Features**
* Explicit version stamping for changelogs (supports .rc/.beta), clearer
prerelease/RC/Beta flows, automated changelog PR creation, and
consolidation of duplicate changelog headings.

* **Tests**
  * Added/updated tests to verify changelog consolidation and ordering.

* **Chores**
* Improved bump confirmation messaging and expanded workflow
documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
justin808 added a commit that referenced this pull request Apr 6, 2026
## Summary
- remove stale  files when running 
- only remove when files are known stock/generated webpack config files
- preserve directory and warn when custom files are present
- add generator specs for both cleanup and preservation paths

Fixes #2549

## Testing
- Inspecting 2 files
..

2 files inspected, no offenses detected
- Run options: include {focus: true, locations:
{"./react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb"
=> [559, 632]}}
..

Finished in 44.88 seconds (files took 1.28 seconds to load)
2 examples, 0 failures

Run options: --seed 2821

# Running:



Finished in 0.000584s, 0.0000 runs/s, 0.0000 assertions/s.

0 runs, 0 assertions, 0 failures, 0 errors, 0 skips

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because the generator now conditionally deletes
`config/webpack/` based on file/content matching, which could remove
expected files if detection is wrong, though it attempts to preserve
custom/unknown files and warns instead.
> 
> **Overview**
> Fixes `--rspack` installs leaving behind stale `config/webpack/` by
adding a cleanup step that **removes the directory only when it contains
known stock/generated webpack configs**; otherwise it preserves the
directory and emits a warning listing custom/unknown files.
> 
> The generator now tracks managed webpack template files and renders
templates via `ERB` to verify file contents before deletion, and specs
add coverage for both the removal path and the preservation path when
custom webpack files are present.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
474a075. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Conservative, automatic cleanup of stale Webpack config when switching
to Rspack, while preserving user-customized files and using
template-aware comparisons to avoid removing modified configs.
* Automatic generation or replacement of Rspack configuration where
appropriate.

* **Tests**
* Added comprehensive tests validating cleanup, preservation,
legacy-file removal, and Rspack generation across transition scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
justin808 added a commit that referenced this pull request Apr 6, 2026
## Summary

- **Add PR #2597** (clean stale webpack config on `--rspack` install) to
changelog under `#### Fixed`
- **Stamp `16.4.0.rc.10`** version header with today's date
- **Improve `/update-changelog` skill**: auto-commit/push/PR after
stamping, ask for confirmation on ambiguous version bumps

## Test plan

- [ ] Verify CHANGELOG.md formatting and version links are correct
- [ ] Verify `/update-changelog` skill reads correctly for future
invocations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only updates to the changelog and the Claude
`/update-changelog` command instructions; no runtime code paths changed.
> 
> **Overview**
> Stamps a new `### [16.4.0.rc.10] - 2026-03-14` section in
`CHANGELOG.md`, folding in the `--rspack` stale `config/webpack/`
cleanup fix and updating the compare links.
> 
> Updates the `/update-changelog` command docs to (1) require explicit
user confirmation when the suggested bump type is ambiguous and (2)
switch release/rc/beta mode guidance from manual “commit/push” steps to
**automatically creating a branch, committing, pushing, and opening a
PR** after stamping.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
596cc76. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Ruby 3.4 heredoc compatibility, pnpm workspace setup guard, SSR error
serialization, CSS module SSR behavior, stale webpack cleanup, and
private path handling on fresh installs.

* **New Features**
* Explicit version stamping for changelogs (supports .rc/.beta), clearer
prerelease/RC/Beta flows, automated changelog PR creation, and
consolidation of duplicate changelog headings.

* **Tests**
  * Added/updated tests to verify changelog consolidation and ordering.

* **Chores**
* Improved bump confirmation messaging and expanded workflow
documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex PRs created from codex-named branches

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Clean up stale config/webpack/ files when installing with --rspack

1 participant