rfcs
rfcs copied to clipboard
Middleware options to run only on server or client
TLDR
I would like to implement some way for middleware to be ran in the context of server/client/isomorphic on a per middleware basis.
Problem
Example Playground with Router, Layout and Page middleware
At the moment we are able to control how middleware are applied on a global basis using the mode
of either ssr or universal.
Mode | Application of middleware |
---|---|
ssr | Runs middleware on client page boot and each page transition |
universal | Runs middleware on server render and each page transition |
What this means it that if i have something like a middleware
that should only run on the client pages but I am running in universal
mode I don't have the option to use the middleware system completely for my concern.
Proposed API
Current middleware would continue to work as is in the way above.
I propose adding annotations to middleware similar to how we handle plugins.
/middleware
/middleware.client.js
/middleware.server.js
This would allow me as a developer who has specific needs to tell nuxt which contexts i would like to run my middleware in without affecting the current implementation in any way.
I would expect these annotations to work in this way.
Middleware File Name | Application of middleware |
---|---|
*.client.js |
Runs middleware on client page boot and each page transition |
*.server.js |
Runs middleware on server render only |
*.js |
Fallback runs in the way that it always had with using the mode to determine application |
I am totally open to implement this feature if it is desirable.
Updates
- Removed isomorphic.js option that would run on both client and server
Thanks for the proposal @Austio -- I'm not opposed to it, except there should be no isomorphic.js
suffix to follow the standard adopted by plugin definitions (client.js
and server.js
or none for universal). Nuxt 3 is undergoing some architectural changes which might already cover this usage so I'll let @pi0, @Atinux and @clarkdo chime in when they can.
A way to always run middleware on client-side, even on the first request which is rendered server-side would be great, but I'm not sure if it's possible w/ the current architecture without changing the order. However, this is just a side note, haven't looked into it :relaxed:
Nice idea. Two points:
- Server-only middleware are acting exactly the same as a plugin. Run once for each request with the possibility to redirect and access context.
- Current middleware does not support async. Should we consider also supporting async/await?
There is currently bug in nuxt-i18n
(https://github.com/nuxt-community/nuxt-i18n/issues/378) that is due to middleware not running on initial request with mode: universal
+ nuxt generate
.
Since that middleware has handling for both server and client, I don't see how to fix that using this solution. I would need the behavior for initial request to be:
- universal (server: yes, client: no) - same as current
- spa (server: --, client: yes) - same as current
- universal+generate (server: --, client: yes) - current is "client: no"
- spa+generate (server: --, client: yes) - same as current
So to fix that case, I would need only that one case to change and I don't see how to fix that using this proposal.
(I can fix it in different way probably, but that's besides the point)
To make a page middleware only run on the client, I followed the advice of this post and used a serverMiddleware to force spa
on those pages.
In my case, I want my /account pages to always behave in SPA mode.
// middlewares/client-only-pages.js
export default function (req, res, next) {
if (req.url.match(/^\/account/)) {
res.spa = true
}
next()
}