rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Middleware options to run only on server or client

Open Austio opened this issue 5 years ago • 5 comments

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

Austio avatar May 15 '19 18:05 Austio

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.

galvez avatar May 15 '19 19:05 galvez

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:

manniL avatar May 16 '19 18:05 manniL

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?

pi0 avatar May 16 '19 19:05 pi0

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)

rchl avatar Sep 04 '19 14:09 rchl

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()
}

weotch avatar Feb 18 '22 22:02 weotch