Explain Propshaft::MissingAssetError from a stale asset manifest - #72
Conversation
ReActionView's dev-tools assets were not found when using Propshaft (Rails 8's default asset pipeline) because it used Sprockets-specific asset path registration. Changed from Rails::Railtie to Rails::Engine, which automatically registers app/assets directories with both Sprockets and Propshaft.
|
@marcoroth No rush, but small bump |
Co-authored-by: Chris Oliver <excid3@gmail.com>
|
Ok, I've dug deeper into this. It was kind of my fault by doing something weird, but this might still be relevant. To reproduce:
@marcoroth You might not run into this if you've never precompiled assets locally. Without a manifest, Propshaft falls back to its Dynamic resolver which checks the load path at runtime and finds the assets just fine. But because ReActionView registers its assets as a Railtie instead of an Engine and Propshaft only auto-discovers assets from Engines, ReActionView's dev-tools JS files never make it into the precompiled manifest. If that manifest is lying around in development (e.g. from a production precompile), Propshaft uses that and doesn't find the assets. |
Propshaft::MissingAssetError from a stale asset manifest
marcoroth
left a comment
There was a problem hiding this comment.
@mickeytgl thanks for sticking with this, and sorry it sat for so long.
Your follow-up comment was the missing piece. I could never reproduce it because I'd never precompiled locally, so Propshaft always fell back to its Dynamic resolver and found the assets fine. One RAILS_ENV=production bin/rails assets:precompile in one of my apps and I hit it immediately.
I've repurposed this PR rather than opening a new one, since the investigation lives here. It now reverts the Rails::Railtie -> Rails::Engine change and instead adds a development-only middleware that catches the Propshaft::MissingAssetError, checks whether public/assets/.manifest.json is actually missing the dev tools assets, and replaces the error with one that names the cause and the fix.
Thank you! 馃檹馃徏
Note
This pull request was opened by @mickeytgl and has been repurposed. The original description is kept below for context. The
Rails::RailtietoRails::Enginechange it proposed is no longer part of this branch. See "Update" for what this ships now.ReActionView's dev-tools assets were not found when using Propshaft because it used Sprockets-specific asset path registration.
Changed from Rails::Railtie to Rails::Engine, which automatically registers app/assets directories with both Sprockets and Propshaft.
I did notice the comment suggesting to put
config.assets.precompile -= ReActionView::Railtie::PRECOMPILE_ASSETSin the initializer once I dug in and that works well, but I think it's still worth it since this would fix the root cause and it saves some time for people on propshaft from running into an errorExample
Update
@mickeytgl worked out the actual mechanism in a later comment, and it turned out to be worth a change of direction.
This pull request now ships only a development-only middleware that explains the failure. It no longer touches how the assets are registered.
Propshaft chooses its resolver based on whether
public/assets/.manifest.jsonexists. With a manifest it usesPropshaft::Resolver::Static, which only knows what was precompiled and never scans the load path.ReActionView registers its
app/assets/javascriptsdirectory only whenReActionView.config.development?is true, so a production precompile never includes the dev tools assets. Leave that manifest behind in development and every page render fails, even though the files are sitting right there on the load path.To reproduce:
RAILS_ENV=production bin/rails assets:precompile bin/dev # visit any pageThis is why the failure looked so arbitrary, and why it was never reproducible for me. Without a manifest, Propshaft falls back to its
Dynamicresolver and finds the assets fine, so anyone who has never precompiled locally will never see it.Before
After
Related #92