/builds
DirectoryI'm working on a Rails 7 application where I'm using Import Maps for JavaScript and CSS Bundling via Yarn instead of Sprockets. Despite following the setup instructions, my assets aren't being served correctly from the /builds
directory.
When loading my homepage, the CSS file is not found, and I get the following error in the browser console:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
Request URL: http://localhost:3000/stylesheets/application.css
The rendered HTML for the home page includes:
<link rel="stylesheet" href="/stylesheets/application.css" media="all" data-turbo-track="reload">
However, my CSS file is located at /app/assets/builds/application.css
.
app/assets
├── builds
│ └── application.css
├── config
│ └── manifest.js
├── stylesheets
│ ├── application.bootstrap.scss
│ ├── application.scss
config/environments/development.rb
:Rails.application.configure do
config.cache_classes = false
config.eager_load = false
config.consider_all_requests_local = true
config.server_timing = true
config.hosts << "improvement.rocks"
if Rails.root.join("tmp/caching-dev.txt").exist?
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :memory_store
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
config.active_storage.service = :local
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
config.active_support.deprecation = :log
config.active_support.disallowed_deprecation = :raise
config.active_support.disallowed_deprecation_warnings = []
config.active_record.migration_error = :page_load
config.active_record.verbose_query_logs = true
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
}
end
app/assets/config/manifest.js
://= link_tree ../images
//= link_tree ../builds
app/views/layouts/application.html.erb
:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Improvement.Rocks</title>
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet">
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbo-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbo-track': 'reload' %>
<%= javascript_importmap_tags %>
<%= csrf_meta_tags %>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header page-scroll">
<a class="navbar-brand" href="#page-top">The Improvement Project</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<%= render 'layouts/navigation_links' %>
</ul>
</div>
</div>
</nav>
<main role="main">
<%= yield %>
</main>
</body>
</html>
Ensured that application.css
is generated in the /builds
directory using the following Yarn script:
"scripts": {
"build:css": "yarn build:css:compile && yarn build:css:prefix",
"build:css:compile": "sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules",
"build:css:prefix": "postcss ./app/assets/builds/application.css --use=autoprefixer --output=./app/assets/builds/application.css",
"watch:css": "nodemon --watch ./app/assets/stylesheets/ --ext scss --exec "yarn build:css"",
"build:js": "esbuild app/javascript/application.js --bundle --outfile=app/assets/builds/application.js"
}
Added public file server configuration in development.rb
.
I need help understanding why the assets are not being served from the /builds
directory and why the generated HTML still references /stylesheets/application.css
instead of /builds/application.css
. I'm at a loss for the next step.
You still need sprockets:
# Gemfile
gem "sprockets-rails"
The only alternative to sprockets is propshaft.
cssbundling-rails
compiles css, then sprockets does the actual serving and precompilation for production and it handles asset urls.
why the assets are not being served from the
/builds
Nobody's there to serve them. Sprockets serves asset from /assets
url, when a request comes in rails will look in /public/assets
for the exact match then sprockets will look in asset paths (Rails.application.assets.paths
) and respond with a first matching file (ignoring the digest part):
# sprockets generates the url
>> helper.stylesheet_path("application")
=> "/assets/application-a72913f4c604bc8f97dd576fc8777bf029401f6af0e14b6a6c9d3874acfe73e4.css"
# and responds with a file
>> Rails.application.assets.find_asset("application.css").filename
=> "/home/alex/code/stackoverflow/app/assets/builds/application.css"
>> Rails.application.assets.find_asset("application.css").source
=> "/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid
...
JavaScript: Using Import Maps
You're using esbuild
and importmaps just load esbuild bundle. Pick one or the other, not both.
https://github.com/rails/importmap-rails#installation
https://github.com/rails/jsbundling-rails#installation
Don't need javascript_include_tag 'application'
with importmaps.