React on Rails

repository·main·Indexed 26 days ago

https://github.com/shakacode/react_on_rails

Integrates React into Ruby on Rails applications using Rails view helpers, server-side rendering (SSR), hot reloading, and automatic bundle generation. It enables developers to maintain a single Rails application instead of splitting the project into separate frontend and API services.

Tokens
265.9K
Snippets
574
Records
1.2K
Agent score
89%

What's inside react_on_rails

  1. Overview of React on Rails Pro

    main

    React on Rails Pro is an advanced rendering and performance tier for the open-source React on Rails integration. It is designed for applications requiring higher SSR (Server-Side Rendering) throughput and advanced React features.

    Key features included in the Pro tier:

    • React Server Components (RSC): Support for modern React architecture.
    • Streaming SSR: Progressive rendering of content to the client.
    • Fragment Caching: Caching of rendered output to improve performance.
    • Node Renderer: Dedicated Node.js tooling for SSR.
    • Code Splitting and Bundle Caching: Optimized asset delivery.
  2. Understand ExecJS limitations in React on Rails

    main

    React on Rails uses ExecJS as the default server-side rendering engine. ExecJS evaluates your server bundle in an isolated, synchronous JavaScript context. Because it is synchronous, it cannot wait for asynchronous operations (like Promises or Timers) to complete.

    Key limitations include:

    • No Timer Support: setTimeout, setInterval, clearTimeout, and clearInterval are not supported. React on Rails stubs these to prevent crashes, but callbacks will never execute.
    • No Async/Await: Promises and async/await will not resolve before the HTML is returned.
    • No Browser APIs: The window, document, and DOM APIs are unavailable.
    • No Node.js Built-ins: Modules like fs or path are unavailable.
    • Runtime Specifics: The mini_racer runtime lacks TextEncoder and TextDecoder, which are required by React DOM Server 18+.
  3. Compare Shakapacker React integration options

    main

    When integrating React with Shakapacker (Rails/Webpacker), you can choose between different gems based on your requirements for Props Hydration and Server-Side Rendering (SSR).

    • react_on_rails: Provides full support for Props Hydration, SSR, SSR with HMR, SSR with React-Router, SSR with Code Splitting, and Node SSR (requires React on Rails Pro).
    • react-rails: Provides Props Hydration and SSR.
    • webpacker-react: Provides Props Hydration only.

    If you do not require view helpers for passing props or server-side rendering, you can implement a manual integration using standard Rails content_tag with JSON data attributes and ReactDOM.render in your JavaScript entry point.

  4. Understand the RSC CSS Architecture

    main

    The React Server Components (RSC) CSS loading implementation in React on Rails Pro is distributed across multiple layers to prevent Flash of Unstyled Content (FOUC). It involves build-time discovery, SSR stream injection, client-side hydration waiting, and Ruby-side metadata embedding.

    Note: This architecture is designed to handle the complexities of injecting CSS <link> tags into the HTML stream during SSR. A more unified approach would involve using a webpack loader to wrap 'use client' components with their CSS <link> tags, allowing React's built-in precedence system to manage loading uniformly.

  5. Compare React on Rails with alternative frontend architectures

    main

    When choosing a frontend integration for Rails, consider these primary alternatives to React on Rails:

    • react-rails: A legacy gem in maintenance mode. Use it only for existing projects that do not require modern features like streaming SSR or code splitting. Switching to React on Rails is straightforward via the react_component helper.
    • Inertia.js: A SPA-like architecture where controllers return Inertia responses instead of HTML. It is 'all-or-nothing' per route, meaning you cannot embed React components into existing ERB templates. It is incompatible with client-side routers like React Router or TanStack Router.
    • Hotwire / Turbo: Rails' default approach. Best for CRUD-oriented apps where you want to minimize JavaScript. It is not a React-based solution.
    • Vite Ruby: A build tool integration. It is a build tool only and does not provide React-specific helpers, SSR, or a react_component view helper. You must manually mount components and pass data via data-* attributes or APIs.
    • Next.js + Rails API: A frontend-led architecture where Next.js handles the App Router and RSC, treating Rails as a backend API. This requires separating frontend and backend concerns.
  6. Benefits of integrated React and Rails systems

    main

    For applications that fit the Rails model (document/database-based with heavy business rules), the tight integration offers several advantages over a pure client-side/microservices architecture:

    • Seamless UI Integration: Easily integrate React components into Rails views.
    • Server Rendering: Supports server-side rendering of React on top of Rails, including support for fragment caching of server-rendered HTML and integration with Turbolinks.
    • Hybrid Approach: Allows mixing standard Rails pages (e.g., traditional Rails forms) with React-driven pages within the same application or even on the same page.
  7. Understand the Rspack vs Vite architectural decision

    main

    React on Rails uses Rspack as its default bundler (as of version 17.0.0) instead of Vite. This is a deliberate decision based on the React Server Components (RSC) pipeline requirements.

    Key reasons include:

    • RSC Pipeline Compatibility: The RSC implementation relies on a three-bundle architecture (client, server, and RSC bundles) that uses a specific webpack/rspack plugin contract. Rspack supports this contract natively via RSCRspackPlugin, whereas Vite requires a completely different plugin architecture that is still stabilizing in the wider ecosystem.
    • Incremental Migration: Moving from Webpack to Rspack is an incremental swap because they share the same plugin contract (loaders and manifest plugins), whereas moving to Vite would require a complete rewrite of the RSC pipeline.
    • CI Validation: The Rspack implementation is fully supported and verified by an end-to-end CI gate that ensures RSC routes render and hydrate correctly.

    If you are evaluating the stack, note that while Vite has a superior dev-server model and a larger ecosystem, Rspack provides the necessary hooks for the current React on Rails RSC implementation.

  8. Bundler support and Vite compatibility in React on Rails

    main

    As of the 17.x release cycle, React on Rails does not support the Vite runtime. The project focuses on Shakapacker and Rspack to ensure stable support for the React Server Components (RSC) pipeline, including the react-on-rails-rsc plugin, client/server manifests, and flight chunk handling.

    While Vite is common in the Rails ecosystem (e.g., vite_ruby), React on Rails uses Rspack because it provides production-ready RSC support and high development speed (benchmarked at ~20x build improvements) that Vite currently cannot match for this specific architecture.

    Future Compatibility: To prevent vendor lock-in, the project is moving toward bundler-neutral configuration naming (planned for version 18.0), which will allow for easier integration with Vite or other bundlers in the future.

  9. Compare Client-Side Routing implementations

    main

    The React on Rails client-side routing approach (using TanStack Router and RSC streaming) can be compared to other frameworks based on scope and behavior:

    • vs. Next.js App Router: Unlike Next.js, which owns the entire application via file-system routing, this approach provides persistent layouts and instant navigation for a specific section of a Rails app. React Server Components (RSC) are streamed from a Rails rsc_payload endpoint prepared by your Rails app.
    • vs. Inertia (inertia-rails): Inertia replaces the Rails view layer for every route. This approach is scoped: a React router owns a specific URL subtree, and RSCRoute streams server components rather than just JSON props.

    Current Limitations:

    • No prefetch or bounded RSC payload-cache eviction: Hover/viewport prefetching and production-sized cache eviction policies are not yet implemented.
    • Repeat-visit flash: Navigating away from and returning to an RSCRoute-backed route may cause a brief placeholder appearance because TanStack Router unmounts the outlet component.
    • Turbo coexistence: Turbo is currently scoped-off for the routed section rather than deeply integrated.
  10. Compare React on Rails Pro and Next.js RSC Architectures

    main

    React on Rails Pro and Next.js both implement the same React Server Components (RSC) contract using the same runtime family. Both follow a similar end-to-end shape:

    1. Render Server Components to a Flight payload.
    2. SSR that payload to HTML.
    3. Inline the payload into the HTML (using REACT_ON_RAILS_RSC_PAYLOADS in React on Rails Pro, which is conceptually similar to __next_f in Next.js).
    4. Hydrate from the payload without a re-fetch.
    5. Refetch payload-only RSC data on navigation.

    Key Differences:

    • Ownership & Integration: Next.js integrates RSC into its own controlled framework and Rust-based bundler (Turbopack), enabling features like segment-level routing, prefetching, server actions, and Partial Prerendering. React on Rails Pro bolts RSC onto general-purpose bundlers (webpack or Rspack via Shakapacker), allowing you to add RSC to any existing Rails application without migrating away from Rails.
    • Refetching Behavior: React on Rails Pro refetches the target component's Flight payload, whereas Next.js can fetch changed route-segment diffs.
    • Bundler Support: Rspack reuses the webpack RSC runtime, while Turbopack requires a distinct runtime due to different chunk-loading primitives.
  11. Unified Linting and Formatting Configuration

    main

    The project uses a unified linting and formatting configuration across both Core and Pro packages. Instead of maintaining separate configurations, all ESLint and Prettier settings are managed from the repository root to ensure consistency and simplify CI workflows.

    ESLint

    Linting is managed via a single eslint.config.ts file at the root. Specific rules for Pro-related paths are handled through scoped override blocks within this central configuration.

    Prettier

    Formatting is managed via a single .prettierrc file at the root. The root .prettierignore file controls which files are excluded from formatting, including Pro-specific paths like **/.node-renderer-bundles.

  12. Understand React on Rails licensing

    main

    React on Rails uses a dual-licensing model depending on which version you use:

    • Core (MIT License): The core React on Rails library is free and open-source for any use.
    • Pro (Commercial License): React on Rails Pro is free for non-commercial, educational, and demo use. However, Production Use (including use by non-profits) requires a paid subscription.