Interview Question
"How does asset compilation work in Rails 8?"
The interview question that tests whether the candidate has kept up with the asset-pipeline overhaul. PropShaft, Importmap, Vite, esbuild, Tailwind, Sprockets-as-legacy. What changed, what to pick, and the senior reflexes.
What the interviewer is actually checking
The Rails asset story has been one of the most-churned parts of the framework over the last five years. Sprockets gave way to Webpacker, Webpacker gave way to a constellation of choices (Importmap, jsbundling-rails, cssbundling-rails, PropShaft, Vite-Rails), and Rails 8 cemented a new default.
The interview question filters for whether the candidate knows the current landscape, can pick the right option for a given app, and has thought about the trade-offs. A weak answer says "Sprockets handles it" (out of date by years). A senior answer names PropShaft, Importmap, the role of Tailwind, and when each choice applies.
The mid-level answer
"Rails uses the asset pipeline to compile and serve CSS and JavaScript. In production it precompiles and fingerprints the files. With Rails 8 they switched some defaults around but I think Sprockets is still in there somewhere."
Out of date. Rails 8's default for new apps is PropShaft + Importmap + Tailwind. Sprockets is still available but is no longer the recommended path. The senior answer names the pieces, what each one does, and why the split is cleaner than the old all-in-one Sprockets approach.
The senior answer
Three layers, each handled by a different tool in modern Rails.
1. Serving static assets: PropShaft. "PropShaft replaced Sprockets as the default asset server in Rails 7.1+ and is cemented in Rails 8. It does less than Sprockets did: no Sass compilation, no JavaScript bundling, no asset transformation. It fingerprints files (adds a content hash to the filename) and serves them with appropriate cache headers. That is it. The reduced scope is the feature: PropShaft is small enough to understand."
2. JavaScript: Importmap (default), or Vite, or esbuild. "Importmap is the Rails 8 default. It uses the browser's native module system: a manifest file maps logical names like 'application' to actual JS file URLs, the browser downloads each module separately, no bundling. Right for apps that are mostly Stimulus + Turbo + small libraries. No node_modules, no transpilation step, no build pipeline."
"When Importmap is not enough: jsbundling-rails integrates esbuild, Rollup, or Bun. vite-rails integrates Vite. The right pick when the app uses TypeScript, React/Vue components, or wants HMR for rapid iteration."
3. CSS: Tailwind (most common), or cssbundling-rails. "tailwindcss-rails is the dominant CSS choice in 2026 Rails apps. It runs the Tailwind CLI to compile, watches for changes in dev, and outputs a precompiled CSS file. cssbundling-rails is the generic version: Sass, PostCSS, Bootstrap, whatever bundler you want."
The fingerprint and the manifest
"One thing seniors are expected to know: how does the browser know which fingerprinted filename to request? The answer is a build manifest. .manifest.json in public/assets/ maps logical names ('application.js') to fingerprinted filenames ('application-a4f37c0e.js'). Helpers like javascript_include_tag('application') read the manifest and emit the correct URL into the rendered HTML."
"The fingerprint enables aggressive caching: assets get Cache-Control: public, max-age=31536000, immutable headers because the URL changes when the content changes. Browsers and CDNs cache forever; deploys invalidate by URL change. This is the basic mechanism every modern asset pipeline shares; Sprockets had it, PropShaft has it."
Picking among Importmap, esbuild, Vite
"Three forks of the JS-bundling decision, each fitting a different shape of app."
Importmap (the default). "Right when JS is mostly Stimulus controllers, a sprinkle of vanilla JS, and a few pin-ed libraries from a CDN. Zero build step. Browsers handle module imports natively. Fast dev startup."
esbuild via jsbundling-rails. "Right when you want a bundle but not a full build pipeline. Compiles to a single file, fast, minimal config. The right pick if Importmap is too thin but Vite is too much."
Vite via vite-rails. "Right when the app uses TypeScript, React/Vue components, or benefits from HMR. The dev experience is the best of the three; the production build is on par with esbuild. The right pick for Inertia.js apps and anything with significant frontend complexity."
"The senior heuristic: start with Importmap; switch to Vite when the JS surface grows enough to justify the overhead. Most teams that pick Vite from day one for a CRUD app eventually regret the build-pipeline complexity."
The follow-ups
"What is the difference between PropShaft and Sprockets?" The right answer: scope. Sprockets handled fingerprinting, Sass compilation, JS bundling, ERB asset templates, dependency directives ('//= require'). PropShaft only fingerprints. Other concerns (CSS, JS) are explicitly someone else's job. Sprockets is still available for legacy apps; PropShaft is the new default.
"How does rails assets:precompile work?" The right answer: it runs the asset build chain (PropShaft fingerprinting, jsbundling/Vite/esbuild for JS, Tailwind/cssbundling for CSS) and writes the result to public/assets/. Deploy hosts (Heroku, Render, Kamal) run this during the build phase. The output is what the production app serves.
"How do you handle a CSS framework like Tailwind in development with HMR?" The right answer: bin/dev (the Procfile.dev script Rails 8 ships) starts the Rails server plus a Tailwind watcher in parallel. Tailwind recompiles on file changes; the page picks up the new CSS on reload. For full HMR, Vite is the upgrade.
"What about cache-busting in production?" The right answer: the fingerprint in the filename. application-a4f37c0e.js has its hash in the URL; when content changes, the hash changes, the URL changes, the cache is bypassed. The HTML always references the current hash via the manifest lookup. You never explicitly invalidate cache; the URL change does it.
The principle at play
The 2026 Rails asset story is "small tools composed, not one big tool that does everything." PropShaft fingerprints. Importmap (or Vite/esbuild) handles JS. Tailwind (or cssbundling) handles CSS. Each tool is replaceable; switching one does not break the others. The opposite of the Sprockets all-in-one approach.
The senior call is picking the smallest set of tools that handles your app's actual needs. For a Rails-CRUD app: PropShaft + Importmap + Tailwind. For an Inertia-React app: PropShaft + Vite + Tailwind. For a legacy app on Sprockets: keep Sprockets until the migration cost is paid for by a feature need.