Using netlify edge functions with nuxt3 netlify_edge preset

I have a site hosted on netlify and I am using Nuxt 3. I was using the npm run generate command and I had in my nuxt file structure a netlify directory with edge functions (/netlify/edge-functions/foo.js).

I wanted to move away from SSG and start using SWR and leveraging the cache so rather than pre-rendering the entire site I set the netlify build command to npm run build. This requires the nitro config to be set a bit differently as documented in the netlify docs for using nuxt on netlify:

Nuxt 3 introduces new rendering options, such as server-side rendering (SSR). SSR is supported when you deploy Nuxt 3 to Netlify, but requires configuration when you use Edge Functions.

In my nuxt.config.ts file I set this up

export default defineNuxtConfig({
  nitro: {
    preset: 'netlify_edge'
  }
})

Now when I run this edge function from /netlify/edge-functions/foo.js

export default async (req, context) => {
  return Response.json({ msg: 'foo' })
}

export const config = {
  path: '/foo'
}

I get an error

GET https://my-site.com/foo 404 (Not Found)

It seems this is happening because the nuxt pages directory is scanned and the pages are being served. If there would be a page bar.vue (/pages/bar.vue)

<script setup>

</script>

<template>
  <h1>bar page</h1>
</template>

It appears that this page is being served from the edge which is pretty cool. But how can I set this up that my edge functions in /netlify/edge-functions/foo.js still work?

Another interesting thing is that when the build command runs on netlify, it shows that the edge functions are bundled. When the nitro netlify_edge preset is used though, trying to fetch foo fails since it isn‘t a page.

Short answer is, you can’t. Nuxt needs to allow users to exclude paths their Edge Function will run on. Since their Edge Function runs on all paths, you cannot bypass it.

Ok then my question is, if I run the regular default preset everything works, so if the request hits the origin server and I have “Netlify-CDN-Cache-Control” headers, is it still possible to leverage netlify edge? Or does the deploy target actually have to be the edge? In the nuxt docs it states

With ESR, the rendering process is pushed to the ‘edge’ of the network - the CDN’s edge servers. Note that ESR is more a deployment target than an actual rendering mode.

When a request for a page is made, instead of going all the way to the original server, it’s intercepted by the nearest edge server. This server generates the HTML for the page and sends it back to the user. This process minimizes the physical distance the data has to travel, **reducing latency and loading the page fast

If I use the netlify preset, then the request
hits the origin server, but I would like to still be able to use the netlify specific headers for edge caching with stale while revalidate.

Is it possible to use the edge without the edge being the deploy target?

I‘m having a hard time with this because the docs are very limited.

Netlify Edge !== Netlify Edge Functions.

Netlify has different types of CDNs:

  • Netlify Edge: The CDN network that serves static assets and stores cache
  • Netlify Functions: A gateway to AWS Lambda Functions (restricted to a single region)
  • Netlify Edge Functions: A separate cluster of nodes that runs server-side functionality (runs on Deno)

With the netlify preset, Nuxt generates an AWS Lambda function. This Function, as I mentioned above is restricted to a single region. However, any response from that Function can be cached in the Netlify Edge. So if a cached response already exists in Netlify Edge, The Function would not be invoked.

In the nitro netlify presets source code I can see there is a preset there for netlify and netlify edge. Based on what you just explained, I take it that the netlify_edge preset generates a netlify edge function. Am I correct in assuming that it takes the contents of a page, e.g. pages/index.vue and serves that content as as the body of an edge function? And will using the netlify-cdn-cache-control headers work in both cases? I figured I would have to use nitro route rules to add a header for a page.

Before I answer this, I’d really like to state that you’re asking for help with this on the wrong platform. You need to ask Nuxt for help and clarification as they write and maintain this code.

Moving to the answer, it’s not as simple as simply taking the contents of the page. I’d advise you to go through: Server-Side Rendering (SSR) | Vue.js (vuejs.org) which talks about SSR in Vue. That explains what a framework needs to do (on a high level) to render Vue code on the server and hydrate it in the client.

Automatically? I don’t think so. You’d likely have to configure it yourself. In case of netlify-edge, I don’t think it would be possible to simply use the headers. Edge Functions need to opt into caching: Optional configuration for edge functions | Netlify Docs which I don’t think Nuxt will do. So simply setting the cache control headers would not work.

Your best bet is to use netlify preset and set the headers in there.

Thanks for taking the time to answer this. I‘m going to dig deep into this because I like using netlify a lot as a platform and nuxt has a lot of gotchas and the github discussions aren‘t always easy to get help