Rails 7 - picking up assets automatically in dev doesn't work - ruby-on-rails

For some unknown reason Rails 7 (development environment) doesn't pick up changes in application.js automatically when I hit F5 in the browser. The location application.js is default. I'm using pretty much default setup.
When I run the server, it picks up javascript from some cached version. I need to explicitly rails assets:precompile to make it work.
Importmap looks standard:
# Pin npm packages by running ./bin/importmap
pin "application", preload: true
...
And layout file seems pretty standard as well:
<!DOCTYPE html>
<html>
<head>
<title>Whatever</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="<%= image_path('favicon.svg') %>">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
...
I tried to set config.importmap.sweep_cache = true in my development.rb (as per importmap docs), but it seems there is no effect.
At this point I'm pretty desperate and can't understand why do I need to rails assets:precompile on my development environment.
Also, I'm not running my app on "localhost" domain, it's on something like dev.server-somewhere.com (so it's accessible from anywhere) with SSH redirects, similar to ngrok. Not sure if it's the cause of a problem.
For clarification: I'm looking for no LIVE refresh feature, just the standard approach with F5 page refresh would work.

I have same problem, simply use: rails assets:clobber to clear all precompiled assets. After that the hot reloading will start working again.
if existing precompiled JS assets exist in public/assets/ rails gives them a priority even in development mode (and even when, for example, esbuild or tsc-watch is otherwise working to transpile your source files into app/assets/buils/, which is unrelated to Sprocket hanging onto its old cache)

Normally, assets are "precompiled" only in production/deployed environments. That means that by default there shouldn't be a folder at public/assets/ while you develop (Sprockets compiles assets on-the-fly for you in development mode).
If you accidentally have run rails assets:precompile in development, you'll have an extra folder here (public/assets/) which does not get checked in to your repository.
But if it does exist, then its existence overrides Sprocket's development mode setting to recompile on every pageload, forcing your browser to load the already compiled (and stale) asset from public/assets/...
(Ironically, running rails assets:precompile or rake assets:precompile, while it does force a one-time recompile and seemingly gives you your latest JS compile, doing this in development is typically what causes the problem of Sprockets getting stuck in the first place)
Next, force Sprockets to both delete the public/assets/ folder and then bust the thumbprint cache using:
rails assets:clobber
(alternatively, run rails assets:clean and then touch tmp/restart.txt)
To debug further, set assets.debug = true in your environment file.

I have faced this issue today and I replaced the sprockets with the propshaft. Then it worked! You might look at the upgrade guide.

I was facing the same issue today and simply reverted back to Sprockets and everything worked out of the box after installing the gem. It seems that Sprockets is now optional in Rails 7. I don't know if Sprockets can be combined with Import Maps, though.

Related

Rails 7 css assets are not working in production, need help understanding how the asset pipeline works without webpacker

Trying out rails 7, with tailwind and postcss.
I have a few stylesheets in assets/stylesheets, which I import through a file called imports.css in the same folder.
//imports.css
#import stylesheet1.css;
#import stylesheet2.css;
I then import that file in application.html.erb with the following:
//application.html.erb
<%= stylesheet_link_tag "application", "imports", "data-turbo-track": "reload" %>
On development everything works fine as intended, meshes well with tailwind. Importing works fine due to postcss. However on production (nginx, puma) it tries to pull in those files and fails. For every stylesheet I have, i see in the browser console:
GET https://mywebsite.com/assets/style/stylesheet1.css net::ERR_ABORTED 404 (Not Found)
I am trying to shift my brain over from webpacker in rails 6, not sure what I need to do here... some thoughts:
Do i need to set it up so that the stylesheets get copied over to the public/assets folder or something? Is there a setting to do that in production.rb? (I feel like rails by default should be already doing this)
Do I need to be manually precompiling these assets on deployment?
Help would be appreciated. Thanks!
#stellenberger was right and deserves the credit. In my case their solution of enabling the public file server for static assets fixed this issue for me and immediately started serving the css assets from public. I was already precompiling, they just weren't being served. I am using Rails docker containers on an EC2 in AWS behind an ALB, and there is no local NGINX so the default assumed is not correct for my scenario and needed to be changed.
The config/environments/production.rb file already provides an environment variable that will turn on the public server if present, called RAILS_SERVE_STATIC_FILES so all you need to do is set that environment variable in your build or deploy process. Since it is a presence check, any value will be truthy as the var existence is all that is checked.
Alternatively, you could also set
# config/environments/production.rb
config.public_file_server.enabled = true
in the file instead of using the ENV var, but generally the ENV vars are better than hard-coded configs.
In my case, I changed the default to
# config/environments/production.rb
config.public_file_server.enabled = ENV.fetch("RAILS_SERVE_STATIC_FILES") { true }
that way my default is true and enabled without setting the var, but I can still use the var to disable it if desired.
Do I need to be manually precompiling these assets on deployment?
Yes. Since you're not using a Node workflow now, instead relying on Sprockets and assets directly, you need the precompile step in Production.
Setting the environment variables RAILS_ENV=production and RAILS_SERVE_STATIC_FILES=true did the job for me (with Rails 7.0.4).

Rails asset pipeline not compiling fonts from 3rd party css framework

The Problem
I'm using Semantic UI, the app renders icon fonts perfectly in development:
But don't work in production:
Error Details
In development, this file is available at:
http://localhost:3000/assets/semantic-ui-css/themes/default/assets/fonts/icons.woff2
In production, I get these errors:
planetlauncher.herokuapp.com/:1 GET
https://planetlauncher.herokuapp.com/assets/themes/default/assets/fonts/icons.woff
planetlauncher.herokuapp.com/:1 GET
https://planetlauncher.herokuapp.com/assets/themes/default/assets/fonts/icons.ttf
404 (Not Found)
Background
Webpack was installed bundled with the rails new --webpack:react command.
Semantic UI installed via yarn add semantic-ui-css
Application.css includes:
*= require 'semantic-ui-css/semantic.min.css
assets.rb includes:
Rails.application.config.assets.paths << Rails.root.join('node_modules')
Rails.application.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Also, I cannot precompile assets and must fallback to the heroku assets pipeline because of my react web pack dependence.
I got around this by compiling the assets with webpack - you're already using webpack, so it shouldn't be a big deal.
Create a pack for the stylesheets:
/app/javascript/packs/stylesheets.js
import 'semantic-ui-css/semantic';
Then in your layout (/app/views/layouts/application.html.erb for example):
<%= stylesheet_pack_tag "stylesheets", :media => 'all' %>
I think maybe you forgot compile your assets. So, your assets is not available in production enviroment.
$ RAILS_ENV=production bin/rails assets:precompile
http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
Hope it helps.
Turns out this is a known issue. One of the comments explains this best:
css in node_modules will not work because it's referenced by for example url('asset.css') rather than asset-url('asset.css') (which would get the fingerprinted url)
-- Sam Peacy
I also posted this as an issue to rails/rails, and this doesn't seem to be something Rails is going to fix:
No plans to fix, neither workarounds. This problem also exists with any pure css libraries that don't use rails helpers and are not installed via yarn.
-- Rafael France

Converting Ember Rails app to phonegap

I have just start using both Ember and Phonegap and I am using the Ruby on Rails Ember-Rails gem as wanted to use Rails to do the asset pre-compilation. I can use rails s to run the Ember app and all works fine. To get into a phonegap app, I am doing a rake assets:precompile command, then copying the fingerprinted css and js files to an assets directory and modifying the index/html file to pick them up as follows:
<!DOCTYPE html>
<html>
<head>
<title>MahimanagerPhoneApp</title>
<link rel="stylesheet" media="all" href="./assets/application-f82ab2dfef6aa5b0589d092d8949fc1e6126d774e74d5a024c1407a7082732f6.css"/>
<script src="./assets/application-0df5442d7ea56c8d2a38022448c2c9b57397f561885306bbdfff8db7962547c3.js"></script>
</head>
<body>
<div id="ember-app"></div>
</body>
</html>
I then copy the index.html and the assets into a phonegap app directory. When I use the phonegap cli to build the app and launch it on on emulator it comes up with "Application Error - The connection to the server was unsuccessful. (file:///android_asset/www/index.html)". I have tried the various solutions in this post :Application Error - The connection to the server was unsuccessful. (file:///android_asset/www/index.html)
but none resolved my problem. When I open the index.html in a browser I get Uncaught UnrecognizedURLError: /home/paul/Documents/testapp/www/index.html which is coming from somewhere within the ember.js file but I assume this is only because it was loaded from the file system rather than severed from a host.
I have looked into the phonegap-rails gem too, but it looks like the commands it expects to run in phonegap are from an older version and no longer work.
I am not really sure where to go from here, and maybe its just not a good idea to try and do this from rails?
UPDATE:
I gave up on trying to get this to work. I have instead gone with the ember-cli-cordova option (https://github.com/poetic/ember-cli-cordova). Which had a few minor stumbling blocks that were all easily solved and now I am up and running....
If you change the locationType in your environment.js file to 'hash', rather than 'auto', you will solve this issue.
The issue is that phonegap access your app at a url such as file:///android_assets/www/index.html
ember tries to resolve the index.html as a route when the locationType is set to auto.

Rails asset pipeline javascript_include_tag jquery doesn't work in production

I pulled my "require jquery" line out of my main application.js (because I have a need for it to be loaded in the HEAD section) and so in the HEAD section of my layout I have this line:
<%= javascript_include_tag "jquery" %>
In development environment that works fine and creates this HTML:
<script src="/assets/jquery.js?body=1"></script>
Which works (however I noticed there is no jquery file in the assets/javascripts directory, strange)
However in production this link gets generated as:
<script src="/javascripts/jquery.js"></script>
Which does NOT work. I noticed most of the javascript gets minified and the names get mangled (probably for caching purposes) in production. But since this file never existed in the javascript folder to begin with I'm guessing that's the problem. Is it because this library was added through a rails gem?
<%= javascript_include_tag "jquery" %>, this worked because you have added jquery.js to your assets/javascripts path. Then in development mode, any file inside assets folder can be accessed.
You can view the included assets by inspecting Rails.application.config.assets.paths in the Rails console.
In Production environment, all assets needs to be compiled and are written to the location specified in config.assets.prefix. By default, this is the public/assets directory. And those we have specified in the manifest files will only be precompiled. So, I think for production, you need to include it in the manifest file, application.js by default (//= require jquery) to be precompiled and to be available for serving in production.
To know more about asset pipeline, please refer here.
Hope it helps :)

Repair git -fd clean mistake ? Now seeing "cannot load such file -- less"

Without understanding, I mistakenly ran git clean -fd and saw this:
perrys-MacBook-Pro:pc perry_mac$ git clean -fd
Removing log/
Removing public/system/
Removing tmp/
Now, when I run rails s and load http://localhost:3000/ I get:
LoadError at /
cannot load such file -- less (in /Users/perry_mac/rails_projects/pc/app/assets/stylesheets/bootstrap_and_overrides.css.less)
Rails Better Errors shows that the exception happens in line 7
app/views/layouts/application.html.erb
2 <html>
3 <head>
4 <meta name="viewport" content="width=device-width, initial-scale=1.0">
5 <title><%= content_for?(:title) ? yield(:title) : "Some Cases" %></title>
6 <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "Some Radiology Cases" %>">
7 <%= stylesheet_link_tag "application", :media => "all" %>
8 <%= javascript_include_tag "application" %>
9 <%= csrf_meta_tags %>
10 <%= yield(:head) %>
11 </head>
12 <body>
Having now read more on git clean I fear I Have made a terrible mistake. In truth, I don't understand what I may have lost. The output of
Removing log/
Removing public/system/
Removing tmp/
... seems innocuous enough. Am I just one step away from getting my app running again or is it something worse? I understand that whatever git clean -fd removed is unrecoverable.
Here is a pastebin of my gemfile, which I think has all the expected gems.
Here is a pastebin of my .gitignore file.
I am further confused because /config/database.yml is in .gitignore, but the file was not deleted.
Please address your answer towards these two points:
1) Based on the output, is there a simple way to know what files I have lost? What is now gone?
2) Why has my rails app stopped working and what's a good next step to fix it?
ADDENDUM 1:
I ran bundle install
I ran rails g bootstrap:install less
perrys-MacBook-Pro:pc perry_mac$ rails g bootstrap:install less
SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
This poses a security threat. It is strongly recommended that you
provide a secret to prevent exploits that may be possible from crafted
cookies. This will not be supported in future versions of Rack, and
future versions will even invalidate your existing user cookies.
Called from: /Users/perry_mac/.rvm/gems/ruby-1.9.3-p327/gems/actionpack-3.2.8/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `initialize'.
insert app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
identical app/assets/javascripts/bootstrap.js.coffee
conflict app/assets/stylesheets/bootstrap_and_overrides.css.less
Overwrite /Users/perry_mac/rails_projects/pc/app/assets/stylesheets/bootstrap_and_overrides.css.less? (enter "h" for help) [Ynaqdh] Y
force app/assets/stylesheets/bootstrap_and_overrides.css.less
create config/locales/en.bootstrap.yml
gsub app/assets/stylesheets/application.css
gsub app/assets/stylesheets/application.css
Now I see this error:
/Users/perry_mac/rails_projects/pc/app/assets/stylesheets/application.css.scss has already been required
I think this may be because:
app/assetts/stylesheets/application.css
app/assetts/stylesheets/application.css.scss
both contain:
*= require_self
*= require_tree .
Can you suggest the best way to resolve this cyclical require?
If I delete the contents of app/assetts/stylesheets/application.css and save the empty file, my application loads and runs, but there is no styling applied.
Removing log/ and tmp/ isn't that problematic, however, public/system can be problematic. Most upload gems put their uploaded files there.
no, unless you have a list what was in there before.
did you try bundle install? Maybe bundle clean before as well. Depending on what gem you used to get twitter bootstrap working, follow the install steps again. From that error message, you are at least missing the bootstrap stylesheet files. If you reinstall the relevant gems, it should work again.
Edit concerning your addition:
It seems like the less installer created a application.css, while you already had a application.css.scss. You should be fine by just deleting application.css (check the content before). However, I wonder, are you using scss and less together in a project? That might result in problems in the long run.

Resources