React, Rails, Webpack: Best practice for where to place React.render - ruby-on-rails

I have a rails app currently using webpack to create a bundle.js file that is picked up by the asset pipeline.
If I have a page that needs a react component embedded in it, where is the best place to actually call React.render? The react-rails gem does a great job of doing this unobtrusively, but with webpack I just have an entry.js file. Embedding a <script> tag in the page seems wrong (and also doesn't work because the JSX isn't transpiled). Is the right approach to jus have a script (probably in entry.js) that looks for certain placeholders on the page and replaces them with react components on page load?
thanks!

Yes. If you look at the react-starter-kit repo which people have started to use when they begin a new project, the recommended minimalistic way is having a div after your body and loading the bundled js afterwards.

Related

Rails 6 - Should I put my CSS & JS in rails asset pipeline or webpacker or through Amazon Cloudfront? Which is the most efficient?

I use to host my CSS files in the rails asset pipeline and JS on webpacker. I recently realize my webpage has been loading slower and slower.
I ran Chrome lighthouse on my site and found that my CSS and JS assets are "render-blocking resources" and causing my page to load slower.
I've already tried moving all of my CSS and JS over to webpacker (semantic-ui css is still being imported by the rails asset pipeline, had lots of problems trying to make this work but couldnt still)
I notice on Chrome lighthouse that my load time improved marginally, I guess its from the minification of CSS and JS by webpacker but it's no where near the improvements I was looking for.
So my question here is, what is the most efficient method to serve CSS and JS files for rails app?
My app is hosted on Heroku's Hobby Tier.. could this be a factor as well?
Both approaches should allow you to achieve similar results. I don't know rails asset pipeline, but if it's used similarly to webpack it just changes your files on the build time & it's up to you how much code the user gets to download.
First of all, you can check the output size - in webpack, you can check the build standard output, or directly check the files it creates.
One trap you could be failing into with webpack is to have it set up wrongly. It could anything, from not minimizing code when for production build to having loades set up in a way that makes your images included directly inside js as data URL.
One advantage of using webpack, is that allows you to set up more complicated loading logic - for example lazy loading. Here something more about lazy load:
https://dev.to/marcinwosinek/lazy-load-library-in-application-build-with-webpack-5757

Adding Lodash to a new Rails 5.2 app with webpacker

So, using Rails 5.2beta (gem install rails --pre), if you create a new app via rails new myapp --webpack=react... how would I go about incorporating Lodash into my flow from there?
I've mucked around with babel-plugin-lodash and lodash-webpack-plugin to no avail.
The compile doesn't fail if I do something like import { _pick, _map } from 'lodash/array'; ... but those variables are undefined when trying to use them.
I'm a bit lost as I'm both new to webpacker & webpack, and a lot of existing examples seem to target an older version of webpack?
Anyway, thank you for any help...
UPDATE:
Ok, looks like you can just do import map from "lodash/map"
So where are you trying to use lodash from? By this I mean are you sure the files are getting compiled / processed by Webpacker, or are they getting processed via the Asset Pipeline?
On my webpacker project I realized that there's a problem: that yes, regular old Javascript compiled with the Asset Pipeline won't know about the NPM Modules included via Webpack. (or at least the require statements wouldn't work).
Because of this I made a hard rule: all javascript goes where webpacker expect it (app/javascript) and no Javascript goes in app/assets. We only use the asset pipeline for CSS (which works great in our case, as I still don't think React - our frontend framework of choice - has a good story around site wide CSS).

How do you reference 3rd party react components in a Rails app?

I'm building an app using the react-rails gem. This means all assets flow through the rails asset pipeline. In order to access 3rd party javascript libraries, I've been taking advantage of rails-assets.org which bundles javascript packages from bower into your rails environment. Most packages can just be called directly in your javascript code.
So if you add package, take marked the markdown library, you include it like:
gem 'rails-assets-marked', source: 'https://rails-assets.org'
And then can easily call it from any js file in your rails app like:
console.log(marked('I am using __markdown__.'));
However, how do you use packages which are not functions but instead are react components? In a node app, you'd use require() like below. Here's an example with react-clipboard:
var Clipboard = require("react-clipboard");
var App = React.createClass({
render: function() {
return (
<div>
<Clipboard value='some value' onCopy={some function} />
</div>
);
},
But, what do you do to accomplish this in a Rails app?
Even though the package is included in the rails asset pipeline, the react component Clipboard isn't available in JSX. How does one make it available?
There is no way to accomplish this directly using rails only.
To be able to use require("react-clipboard"), one solution (the less intrusive) would be to use a combination of rails, react-rails and browserify as explained here:
http://collectiveidea.com/blog/archives/2016/04/13/rails-react-npm-without-the-pain/
and here
https://gist.github.com/oelmekki/c78cfc8ed1bba0da8cee
I did not re paste the whole code example as it is rather long and prone to changes in the future

Serverside rendering react components in Ruby on rails project without asset pipeline

I'm working on a Ruby on rails 4 project where we are using React/Redux for frontend. We are using Webpack and gulp for compiling javascript and css. We do not use rails Asset pipeline at all, it is disabled from config. All assets compile to public folder and directly included on views. Now all react components are rendering on client side. It is having his own disadvantages like visual flicks before js is fully loaded and problems on passing initial props from backend to frontend.
Is there any good way to compile react components on server side without using asset pipeline and passing props directly from rails views?
I am pretty sure http://reactrb.org does this, but it does use asset pipeline. The webpack components are brought in to the rails side, and then wrappers are automatically built so you can interface to the webpack components from your client side ruby components.
There was a lot of discussion on this at https://gitter.im/reactrb/chat and I don't know the details.
Also tutorial here: http://tutorials.pluralsight.com/ruby-ruby-on-rails/reactrb-showcase dealing with this issue as well.
So you could just use http://reactrb.org or figure it by reading their code.

React, Ruby on Rails: jsx vs html.erb

I'm using the react-rails gem to integrate react with rails, and I'm conflicted on how I should organize my code.
Is it preferable that I have my core html in the html.erb files or in the jsx files? Currently, I basically made everything a component. All I do in my html.erb files is using the react_component helper to call those components. For example, I would have a ProfileShow.js.jsx file for my profile page and a EditPost.js.jsx for my edit post page.
What is your suggestion?
I prefer move my react-component's code to js-files. And link them using react_component helper method. It isn't good practice to write your js-code in views.
There are multiple ways to do this.
One of the best solutions I seen so far is to write your react jsx components in an app/assets/javascripts/components folder.
Setup a react gem like https://github.com/shakacode/react_on_rails
that would help with passing on data as props to the view layer as these would be accessible outside react.
I hope this helps.
Cheers.

Resources