Remix: middleware pattern to run code before loader on every request?

Is there a recommended pattern in Remix for running common code on every request, and potentially adding context data to the request? Like a middleware? A usecase for this might be to do logging or auth, for example.

The one thing I’ve seen that seems similar to this is loader context via the getLoadContext API. This lets you populate a context object which is passed as an arg to all route loaders.

It does work, and initially seems like the way to do this, but the docs for it say…

It’s a way to bridge the gap between the adapter’s request/response API with your Remix app

This API is an escape hatch, it’s uncommon to need it

…which makes me think otherwise, because

  • This API is explicitly for custom integrations with the server runtime. But it doesn’t seem like middlewares should be specific to the server runtime – they should just be part of the ‘application’ level as a Remix feature.

  • Running middlewares is a pretty common pattern in web frameworks!

So, does Remix have any better pattern for middleware that runs before every loader? If so, how do you use it?