#Cache fetch requests in middleware?

24 messages · Page 1 of 1 (latest)

dark quarry
#

Can you cache fetch requests in middleware.ts?

e.g. from an external route

export default async function middleware(request: NextRequest) {
    const redirects = await fetch(`www.external.com/api/redirects`, {
      next: { tags: ['redirect-cache'] },
      cache: 'force-cache',
    });

     ...
});

e.g. from a next.js route

export default async function middleware(request: NextRequest) {
    const redirects = await fetch(`${basePath}/api/redirects`, {
      next: { tags: ['redirect-cache'] },
      cache: 'force-cache',
    });

     ...
});
fluid mortarBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

radiant garden
#

your middleware arent supposed to make fetch calls. its supposed to be lightweight. In vercel, it will also run in a different location than your serverless function so its designed to be "self-contained" thats why fetch behavior is the default cache behavior

#

if you want fetch caching, make a reusable function and use them in your route handlers

dark quarry
#

Ty for the response!

In vercel
We are self-hosting, so it won't be run in a different location

if you want fetch caching, make a reusable function and use them in your route handlers
We are trying to programatically redirect based on a 3rd party list of redirects. So we need to look at every request to decide if we should redirect. Would love to cache this call and handle cache invalidation inside of the middleware, rather than rolling our own

radiant garden
#

hmm

#

thats a solid use case

zinc cosmos
#

@dark quarry i had this same issue once

#

the best method would be to make a server action, give its fetch calls all your caching options and call it

#

route handlers work as well, but i like the feel of server actions

#

normal functions wont work btw

dark quarry
#

@zinc cosmos interesting. Did this make it more performant than just having it in the middleware? This is what I have at the minute...

// middleware.ts
const cachedRequests = null;

export default async function middleware(request) {
  const fetchRedirects = async () => {
    const res = await (
      await fetch(`..../redirects`)
    ).json()
    return res['redirects']
  }

  if (!cachedRequests) {
    cachedRequests = await fetchRedirects()
  } else {
    if (isAllowedToRefetchCache(request)) {
      cachedRequests = await fetchRedirects()
    }
  }

  const redirect = cachedRequests[request.nextUrl.pathname]
  if (redirect) return NextResponse.redirect(new URL(redirect.to))

  // ...
}

... and is this what you're suggesting?

// app/cached-redirects-action.ts
'use server'
 
const cachedRedirects = null;

export async function getCachedRedirects(request) {
  const fetchRedirects = async () => {
    const res = await (
      await fetch(`..../redirects`)
    ).json()
    return res['redirects']
  }

  if (!cachedRedirects) {
    cachedRedirects = await fetchRedirects()
  } else {
    if (isAllowedToRefetchCache(request)) {
      cachedRedirects = await fetchRedirects()
    }
  }

  return cachedRedirects;
}

// middleware.ts

export default async function middleware(request) {
  const redirects = await getCachedRedirects(request)
  const redirect = redirects[request.nextUrl.pathname]
  if (redirect) return NextResponse.redirect(new URL(redirect.to))

  // ...
}

I'm not sure on the implications of calling server actions from middleware

zinc cosmos
#

wel there is a reason why you cant cache middleware requests @dark quarry

#

its a usually bad idea

#

to do any sort of long operation in the middleware

#

but if you need to do it..yes go for a server action

#

youu can use api routes.. i just like calling a function lol

drifting plover
# dark quarry Ty for the response! > In vercel We are self-hosting, so it won't be run in a d...

Nextjs cache doesn’t work there. But since you are self hosting, I suppose you can simply cache in the global object.

Like if global.redirectRules doesn’t exist, then fetch the rules, then save the rules into global.redirectRules. If the global variable already exists, use it.

You can also route requests to be redirected to a route handler, where cache works, then redirect from that route handler.

Server actions are irrelevant here. Do not use them where you don’t need them.

#

Also... don't fetch your own api routes in middleware, except in rare cases where there are no alternatives

zinc cosmos
#

With route handlers you gotta worry abt urls and stuff

#

Actions have good dx lol, but it is very very scuffed doing a post request lmao

drifting plover
# zinc cosmos That's why I usually go the server action route if it's absolutely necessary to ...

server actions are absolutely irrelevant here. middleware is already on the server, so server actions do nothing.

you remember my network boundary tests? these ones #discussions message. if you conduct this test in middleware, you will find that server actions are simply run as normal functions in middleware. the use server directive contributes nothing.

cache doesn't work in middleware, so cache doesn't work in server actions either, considering the above.

there are many cases where server actions cannot replace route handlers. this is one of them.

Discord

Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.

fluid mortarBOT
#
✅ Success!

This question has been marked as answered! If you have any other questions, feel free to create another post

Jump to answer

[Click here](#1240313425872158740 message)