Giter VIP home page Giter VIP logo

hipsterbrown / rails-react-playground Goto Github PK

View Code? Open in Web Editor NEW
4.0 3.0 0.0 809 KB

An example repo setup for serving lazy-loaded React components through Rails using pnpm workspaces, Vite, and custom elements. Read more here: https://hipsterbrown.com/musings/musing/islands-on-the-rails/

JavaScript 0.40% HTML 13.05% TypeScript 11.24% Ruby 75.15% CSS 0.16%
custom-elements rails react typescript vite

rails-react-playground's Introduction

React in Rails Playground

An example repo setup for serving React components through Rails using pnpm workspaces, Vite Ruby, and Catalyst.

Overview

While the original motivation for this setup was to support a monorepo with multiple Rails apps and engines and sharing JS assets, like custom elements and React components, among them, this simplified example shows a nice workflow where the JS assets can be built in isolation with modern tooling and served through the dependent Rails app like any other package.

pnpm workspaces are used to connect the internal JS package with the Rails app without needing to publish the package to a remote registry. The @playground directory is used to allow for multiple internal packages to be scoped under the packages field in the root pnpm-workspace.yaml, but it's not required. @playground/core is scaffolded using create-vite-app and a React template because it is quick and comes with standard tooling for building TypeScript + React packages. The Rails app (playground) is generated without Webpacker, then uses the bundle exec vite install command after adding vite_rails to the Gemfile.

Dev Workflow

When building components before integrating into the Rails app, run pnpm storybook in the @playground/core directory to start the Storybook server. Learn more about Storybook and writing component stories. You'll find an example under the @playground/core/stories/ directory.

To serve a React component in the Rails app, a custom element powered by Catalyst (react-island.tsx) is used to mount the component on demand. Any component file placed in the @playground/core/src/islands directory will be automatically registered by the vite-plugin-react-islands build plugin which is executed through the import 'virtual:react-islands' in the src/index.ts of the core internal package. This is similar to the conventions use by Fresh.

The plugin uses dynamic imports and the React.lazy API to split the bundled component and lazily load one when the custom element requests it.

To invoke the custom element in your Rails view:

<react-island data-name="thing" ></react-island>

Or the ViewComponent can be used instead:

<%= render ReactIslandComponent.new(name: "thing") %>

While iterating on the component in Rails, running foreman start -f Procfile.dev within the Rails directory (playground) and pnpm start within the package workspace (@playground/code) will auto-reload the page when the source files change.

If the React component should receive initial props from the Rails view, that can be done in two different ways:

<react-island data-name="thing" data-props="<%= {propName: 'some value'}.to_json %>"></react-island>

The hash could be an instance variable, it just needs to be stringified JSON data to be parsed by the custom element.

Or:

<%= render ReactIslandComponent.new(name: "thing", initial_props: {propName: 'some value'}) %>

The initial_props argument for the ViewComponent will automatically stringify the hash for the rendered HTML output.

Because the react-island island is lazily-defined, the loading behavior can be controlled through the data-load-on attribute:

<react-island data-name="thing" data-load-on="visible"></react-island>

Or with the companion ViewComponent:

<%= render ReactIslandComponent.new(name: "thing", load_on: 'visible') %>

rails-react-playground's People

Contributors

hipsterbrown avatar

Stargazers

Eric Chernuka avatar Gabriel Talavera avatar Sam Moore avatar Chris LoPresto avatar

Watchers

James Cloos avatar  avatar  avatar

rails-react-playground's Issues

Assets in Islands

@HipsterBrown I'm familiar with the islands concepts also implemented in different frameworks like Astro,etc.
My question around this implementation is how do you expect non js assets living in islands to be handled ?
Talking about imgs and css specifically ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.