One job: turn a source file into a cacheable URL
A file the browser can trust forever, or never
Every stylesheet and script a browser loads needs a URL, and that URL has one hard job: telling the browser how long it can keep the file without asking the server again. Get it wrong one way, and every visitor downloads the same unchanged CSS on every request, wasting bandwidth and time. Get it wrong the other way, and a deploy that changes a file leaves visitors running yesterday's CSS or JavaScript from their cache. Rails' asset pipeline exists to solve this, and Rails 8 solves it with Propshaft, its default gem for the job.
This app's Gemfile has gem "propshaft", under the comment # The modern asset pipeline for Rails [https://github.com/rails/propshaft], and Gemfile.lock pins propshaft (1.3.1). Propshaft replaced Sprockets, the asset pipeline Rails apps used for a decade before it, and this app has never used the older gem. A grep for "sprockets" across the Ruby files, the YAML config, the Gemfile and the lockfile returns nothing. There's no app/assets/config/manifest.js either, the file where every Sprockets app listed its entry points; this app has no app/assets/config directory at all.
What "fingerprinting" means
Both pipelines rely on a filename derived from the content. Instead of tailwind.css, the browser requests something like tailwind-fe18c29a.css: a hash of the file's content, inserted right before the extension. Change one byte of the CSS and the hash changes, producing a new URL. A browser told to cache tailwind-fe18c29a.css forever can do so safely, because when the content changes, the URL changes too. A URL named after its content can't point at stale content. That idea, "the URL is the fingerprint", is the mechanism this course checks over the next six lessons, against this app's installed propshaft-1.3.1 gem, its app/assets directory and its development server.
What this course covers
Lesson 2 shows how Propshaft builds its load path and what this app puts in it. Lesson 3 explains why development needs no separate compile step, checked with requests against this app in development. Lesson 4 covers how url() references inside CSS are rewritten, and how Propshaft and importmap-rails split the work of serving JavaScript. Lesson 5 reads the stylesheet_link_tag calls in this app's layouts and the two ways Propshaft resolves a logical path to a URL. Lesson 6 covers deploy time, from this app's Dockerfile and production config. Lesson 7 traces one file from source to URL, with a challenge built from Propshaft's fingerprinting code.
Keep going with lesson 2
The load path: where Propshaft looks for assets
How Propshaft builds its load path from app/assets and gem directories, and where the generated tailwind.css fits.
A free account also gives you the quizzes, your progress and notes, and the discussion.