Run built frontend (react) as a static file in Rails - ruby-on-rails

So I'm trying to run a React app as a static html file (it's index file) in a Rails app. This works in express/node and it's quite common in projects, but i can't find a solution for this in Rails. So the react app is already built and i'm trying to serve it as a static html from the /public folder. EDIT However i can't get it to run, it shows me that it's loaded, there's no error in the rails console or the browser console, however nothing gets shown on the screen.
routes.rb
get "react_app" => "projects#react_app"
projects_controller.rb
def react_app
render :file => 'public/react_app/public/index.html'
end
i also have
config.serve_static_assets = true
I'm using Rails 5.2. I am not using yarn, i'm trying to run it via the plain assets pipeline.
Any ideas ? Or is there another better way to do it maybe ?
This app needs to be all in one place, and unfortunately gems such as react-on-rails or react-rails are not an option, since they require too much strange customization and often crash due to Redux.

Related

Specific Image Not Loading After Rails 7 ESBuilt Update

I have a very frustrating issue with a Rails 7 app after migrating to Ruby 3.2 with Esbuild.
Basically there is a few specific images that simply will not load, however, there are many others that load just fine that live in the same location, and are accessed the exact same way. It's driving me nuts.
I have cleared cached, restarted servers, cleared all the local build files, everything I can think of. This is also happening in both dev and production.
My Esbuild is running just fine, it is finding the files and compiling them with a finger print. The files all exist and are in the right location. (all sitting under app/assets/builds)
Accessing the file direcly in the browser, ie
http://localhost:4000/assets/logo_white_trans-QEBURZJB.png
Fails with a 404, cannot find the image. This file however exists with the correct name in the app/assets/builds folder.
Accessing another image from the page ie
http://localhost:4000/assets/leadstory-symbol-B5T7OIJB.png
Loads just fine.
It's almost like there is a static list of rails routes that match the images and it is not generating the route for some of these specific images, hence the 404, even though the file exists.
Some screenshots that highlight the odd behaviour
and the files listed in the directory, showing the file clearly exists
My package.json build step is
esbuild app/javascript/bundles/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=/assets --minify --log-limit=0 --loader:.js=jsx --loader:.png=file --loader:.svg=file
And a snip from the app of how its being loaded.
import LogoWhiteTrans from "../../assets/images/logo_white_trans.png";
<img src={LogoWhiteTrans} className="logo" alt="logo" />
Which looks to be working fine, the HTML outputs
<img src="/assets/logo_white_trans-QEBURZJB.png" class="logo" alt="logo">
The image can be loaded fine, from elsewhere in the app in a regular rails view using asset helpers (not from within the React app)
ie <%= asset_path('logo_white_trans.png') %>
Something I have noticed is in the logs, I see
ActionController::RoutingError (No route matches [GET] "/logo_white_trans-QEBURZJB.png"):
Notice there it does not say "/assets/logo_white_trans..."? I thought that was weird, as the URL in the image tag clearly has a /assets at the start. Trying either path does not work, with or without /assets directly in the browser. Just seems odd rails would see it that way
Im going nuts here, what am I missing. Its not a png specific issue, as other pngs are loading fine in the same way, nor is it an image issue the file exists and the naming is fine.
Is there some sort of manifest thats not being updated? An internal asset route list or something along those lines?
Im running Rails 7
Ruby 3.2
ESBuild
This isn't really an answer, but what I have ended up doing is moving all image assets out of the asset pipeline and into the public folder. I noticed that my assets were being duplicated by esbuilt and the rails asset precompile process, and basically the javascript build and rails eco system just do not work well together.
For anyone else having issues like this, we've just moved all our static assets in the public/images folder and we refernce the path /images/blah.png the same way in both React and Ruby now.
All image tags in either React or standard .erb views are just <img src="/images/blah.png/>. Its a lot cleaner.
Yes, we have given up asset finger printing, but its a small loss, considering most images never change and It's dramatically simplified things and sped up our build process considerably as it does not have to touch each file during precompilation.
Our views now also just have standard tags, instead of <asset_path> tags, which im sure is just quicker in general instead of ruby generating these asset strings all the time.
So, not really and answer to the initial question but it is a solution, and one i think anyone who is fusing modern javascript, react, typescript etc into a Rails app.

Is it possible to mount Vue.js components on the DOM in production using Rails, Webpacker?

I have a Rails 5.2.1 app and would like to integrate Vue in a piecemeal fashion; I have everything working nicely in development with Foreman starting Rails and the webpacker dev server together.
I wrapped everything inside the body tag in a div with id="vue-app", and mount the app using the following in packs/app.js:
document.addEventListener('turbolinks:load', () => {
const app = new Vue(Vue.util.extend({ i18n }, App)).$mount('#vue-app')
})
This works fine in development - I can add vue directives on any element and drop in my components wherever I need to. However, when running the same thing in production mode (after asset precompilation), the app fails to mount to #vue-app and just replaces it with an HTML comment. Vue itself is loading fine, compilation appears to be fine, everything is being found - it just silently fails to mount.
I've been researching for a couple of hours, and can't find anything besides duplicates of this: Vue.js app works in development but not mounting template in production with Rails 5.2.0 / Webpacker - blank screen with no errors in console
His solution was to change the mounting to a render function on a new element, but ends with 'I still don't know how to use DOM as template with Vue in production though.'
It severely diminishes the appeal of Vue if it can't be mounted on existing elements, so I'm curious if it is at all possible to use a DOM template in production with Rails/webpacker?
I think I've solved my own problem - I believe it was caused by a mismatch between dependencies in package.json. I may have inadvertently messed it up while I was working on other aspects of the Vue app. I generated a new Rails application, added Webpacker and Vue, confirmed it worked with DOM templates in production with compiled assets, and then copied the versions out of that clean package.json into my existing app.

API-only doesn't load JS/CSS assets properly?

I created an app using api-only flag, and I ran into a problem.
I wanted to install a gem that includes a mountable engine, in which there are JS/CSS assets. When I mounted the engine, I got an error complaining that the JS/CSS files don't exist.
Rails.application.routes.draw do
if Rails.env.development?
mount SomeGem::Rails::Engine, at: "/some-gem"
end
end
When I tried the same on a new app without the api-only flag, it worked great without any hassle. So I am assuming that the api-only flag is affecting the bundle process (maybe excluding all JS and CSS assets?) but I can't find the relevant information in the doc.
What am I missing?
Well I haven't tried Rails 5 yet but, my general understanding is that API only will allow developers write business logic and won't work well with the view layer. Hence, I think you have chosen the wrong development mode. I suggest if you need to do view related development then, you should remove the flag and try to use it.

asset images not precompiled in rails

I was developing this rails app that has mostly static pages. I downloaded a template from bootstrapicious and created a pages controller to hold all my static pages, changed the file names to have a .html.erb extension and the routes. Everything was working out fine in the index page; all images, css and js were working fine. But other pages aren't loading the animate js and images. I created a link of the home pages without using root_path and it behaved the same. I'm stranded and don't know what to do. Please help. quite a newbie in rails.
Stop the Rails server and try this command
rake assets:precompile
After this re-start your rails server!! Let me know if this what you wanted.

Rails application not displaying index.html in development mode

I have placed an index.html file in the public directory of my Rails 4 application but it still shows this deleted file as rails welcome page. I am using Webrick in development mode. I have another app almost identical in setup which works fine.
As written above, Rails 4 has removed the default index.html page in the /public folder. If you want to achieve the functionality anyway, you have to render the page manually. Just create a controller, and render the index page in your chosen controller action like this:
def index
render :file => 'public/index.html' and return
end
EDIT:
If you want to serve the files without using the Rails stack, you have to configure your Web server (Apache/Nginx/whatever) to do so. Configurations for Nginx and Apache.
Additionally, you have to disable Rails' static file rendering in your configuration by setting serve_static_assets to false:
config.serve_static_assets configures Rails itself to serve static assets. Defaults
to true, but in the production environment is turned off as the server software (e.g.
Nginx or Apache) used to run the application should serve static assets instead.
Unlike the default setting set this to true when running (absolutely not recommended!)
or testing your app in production mode using WEBrick. Otherwise you won´t be able use
page caching and requests for files that exist regularly under the public directory
will anyway hit your Rails app.
So, if you want to use this in development mode, set config.serve_static_assets to false in environments/development.rb.
Rails 4 uses dynamic index.html. Read on http://blog.remarkablelabs.com/2012/12/dynamic-index-html-rails-4-countdown-to-2013
Press F5 in navigator, the index can be in the cache.

Resources