sprocketsruby-on-rails-7stimulusjsimport-mapsstimulus-rails

importmap-rails + sprockets not finding stimulus-loading.js in fresh stimulus-rails installation


Mature app updating to Rails 7.0.7, Ruby 3.1.2, adding stimulus-rails using the installer, with importmap-rails, turbo-rails and sprockets-rails already installed. No custom Stimulus controllers yet, just trying to load the setup "out of the box".

I've read through a dozen Q/A's about this on StackOverflow, including Alex's lengthy and good explanations of how importmap-rails works, but none of them seem to explain this case.

When I boot the server locally, i'm getting

ActionController::RoutingError (No route matches [GET] "/stimulus-loading.js"):

Everything seems right in the importmap:

Here is the result of ./bin/importmap json:

{
  "imports": {
    "application": "/assets/application.js",
    "@rails/ujs": "/assets/@rails--ujs.js",
    "@hotwired/turbo-rails": "/assets/turbo.min.js",
    "@hotwired/stimulus": "/assets/stimulus.min.js",
    "@hotwired/stimulus-loading": "/assets/stimulus-loading.js",
    "controllers/application": "/assets/controllers/application.js",
    "controllers/hello_controller": "/assets/controllers/hello_controller.js",
    "controllers": "/assets/controllers/index.js"
  }
}

I have run rails assets:clobber as suggested in several answers. Here's the standard setup, these lines all added by the installers for turbo-rails, importmap-rails and stimulus-rails gems.

# config/importmap.rb

pin "application", preload: true
pin "@rails/ujs", to: "@rails--ujs.js" # @7.0.7
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
# application.js

import "@hotwired/turbo-rails"
import Rails from "@rails/ujs"
import "@hotwired/stimulus"
import "@hotwired/stimulus-loading"
Rails.start(); import "controllers"

Here's my assets/config/manifest.js

//= link_tree ../images
//= link_tree ../javascripts .js
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js

//= link my_application.js

I renamed app/assets/javascripts/my_application.js to avoid naming conflict with app/javascript/application.js

I've added app/javascript to the asset path (didn't seem to change anything)

# config/initializers/assets.rb

Rails.application.config.assets.paths << Rails.root.join("app/javascript")

I've added asset debugging and tried turning on/off compiling

# config/environments/development

config.assets.compile = true # if false, no assets found
config.assets.debug = true # didn't tell me anything new

Log of page load in dev mode:

Started GET "/assets/es-module-shims.min.js" for 10.0.2.2 at 2023-09-06 16:47:39 +0000
10.0.2.2 - - [06/Sep/2023:16:47:38 UTC] "GET /assets/es-module-shims.min.js HTTP/1.1" 304 0
http://localhost:3000 -> /assets/es-module-shims.min.js
Started GET "/assets/BlackOnWhite.css" for 10.0.2.2 at 2023-09-06 16:47:40 +0000
Started GET "/assets/my_application.js" for 10.0.2.2 at 2023-09-06 16:47:41 +0000
10.0.2.2 - - [06/Sep/2023:16:47:38 UTC] "GET /assets/mo_application.js HTTP/1.1" 304 0
http://localhost:3000 -> /assets/mo_application.js
10.0.2.2 - - [06/Sep/2023:16:47:38 UTC] "GET /assets/BlackOnWhite.css HTTP/1.1" 304 0
http://localhost:3000 -> /assets/BlackOnWhite.css
Started GET "/assets/application.js" for 10.0.2.2 at 2023-09-06 16:47:42 +0000
10.0.2.2 - - [06/Sep/2023:16:47:42 UTC] "GET /assets/application.js HTTP/1.1" 200 367
http://localhost:3000 -> /assets/application.js
Started GET "/assets/stimulus.min.js" for 10.0.2.2 at 2023-09-06 16:47:44 +0000
Started GET "/assets/controllers/index.js" for 10.0.2.2 at 2023-09-06 16:47:44 +0000
Started GET "/assets/turbo.min.js" for 10.0.2.2 at 2023-09-06 16:47:45 +0000
10.0.2.2 - - [06/Sep/2023:16:47:43 UTC] "GET /assets/stimulus.min.js HTTP/1.1" 304 0
http://localhost:3000 -> /assets/stimulus.min.js
Started GET "/assets/stimulus-loading.js" for 10.0.2.2 at 2023-09-06 16:47:46 +0000
10.0.2.2 - - [06/Sep/2023:16:47:43 UTC] "GET /assets/turbo.min.js HTTP/1.1" 304 0
http://localhost:3000 -> /assets/turbo.min.js
  
ActionController::RoutingError (No route matches [GET] "/stimulus-loading.js"):
  
10.0.2.2 - - [06/Sep/2023:16:47:43 UTC] "GET /assets/stimulus-loading.js HTTP/1.1" 404 0
http://localhost:3000 -> /assets/stimulus-loading.js
10.0.2.2 - - [06/Sep/2023:16:47:43 UTC] "GET /assets/controllers/index.js HTTP/1.1" 304 0
http://localhost:3000-> /assets/controllers/index.js

It seems from the log that there may be a path discrepancy between /assets/stimulus-loading.js and /stimulus-loading.js. But the browser is showing a 404 for http://localhost:3000/assets/stimulus-loading.js.


Solution

  • Solved.

    Occurred to me to check issues on the stimulus-rails github page, and this is a known current issue, related to a current Sprockets issue with 4.1.1 where the hyphen in the name "stimulus-loading.js" makes Sprockets skip it because it thinks it's a digest.

    The solution is setting config.assets.digest = true in config/environments/development.rb. According to the linked Stimulus issue, this is the Rails team's preferred setting for development, but it's been off in my legacy app since before my time.