File locations Javascript vs Stylehseet in Rails 7

Viewed 75

In a new default Rails 7 application using the import maps functionality, Javascript is stored in app/javascript, while CSS is located in app/assets/stylesheets. Not only are they located at different hierarchy levels, but javascript is singular, while stylesheets is plural.

I'm looking for sources that explain these divergent locations and pluralization decisions. Searches through Rails Guides and API documentation have turned up nothing, but support talk on the Rails repo suggests that docs are still being actively updated.

On the surface this seems really shortsighted, but I want to make sure I'm not missing something before I go messing with the defaults.

1 Answers

app/assets is used by sprockets. This is rails asset pipeline. Preprocessing, minification, compilation etc. app/assets/javascripts was a thing before javascript took over the world, and had to be given its own separate directory.

app/javascript was used by webpacker to avoid mixing it with sprockets processing. This is javascript pipeline that does what sprockets does, process, compile, minify etc. A way to bring javascript build tools into rails. Singular referring to "javascript" language not "javascripts" as in collection of js files (I guess).

Both of these directories can have css and js assets, just processed and compiled by completely different tools.

In rails 7, app/javascript is used by jsbundling-rails that comes with different js build tools, like, esbuild and webpack. After javascript is done its job, bundles go into app/assets/build where sprockets treats it as any old js or css file.

With importmaps there is really no processing but app/javascript is the logical place for it. To use importmaps, all the files in app/javascript have to be precompiled by sprockets for use in production:

// app/assets/config/manifest.js

//= ../../javascript .js

and app/javascript has to be in Rails.application.config.assets.paths:

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

This is what importmap-rails does, among other things. In case you want to relocate anything back to app/assets.

Here is a short overview of who lives where:

app/
├─ assets/          # used by sprockets-rails, everything else hooks into it
│  ├─ build/        # compiled assets (jsbundling-rails, cssbundling-rails, tailwindcss-rails)
│  ├─ config/       # precompile `build/` if any of these three ^ are used
│  │                #  or precompile `app/javascript/` if importmap-rails is used
│  ├─ stylesheets/  # used by cssbundling-rails, tailwindcss-rails
│  └─ javascripts/  # not used in rails 7, but any directory can be added to `assets/`,
│                   #  just add it to precompilation manifest as well https://stackoverflow.com/q/72305291/207090
└─ javascript/      # used by jsbundling-rails, importmap-rails and anything node related.
   └─ controllers/  # used by stimulus-rails   

Also, rails gems themselves use app/assets/javascripts to ship any js files.

Related