Cloudflare Pages - Cached Subrequest / SSR fetch
Hey there, im using Nuxt in a Cloudflare pages runtime.
Using
useFetch
or useAsyncData
on the initial request (SSR) will not do a "real" request, as long the target path is located in server/api
routes, correct?
It just calls the defineEventHandler
, instead of calling the url like useFetch
would do it on client-side.
This could be a problem, when you start to cache api responses through e.g. Cloudflare. That's because the fetch on server-side (uncached) and client-side (cached) can receive different states.
Is there any logic/option to force the fetch method to do an "external request" even on server-side?7 Replies
it should still give the same state given that cache of an event handler will still be considered
(except when the cache misses on the client side)
But the request is never going out of the stack on SSR, right?
So there is no DNS resolving, which means, the request on server-side-rendering e.g. with
useFetch('/api/my-api')
never reaches cloudflare.
Client side request order:
1) useFetch('/api/foo')
2) GET https://example.com/api/foo
3) Cloudflare => Cache Hit?
3.1) Yes => Cloudflare response
3.2) No => Request to my Nuxt Application, which triggers defineEventHandler
SSR request order:
1) useFetch('/api/foo')
2) call defineEventHandler()
I played around a bit. I thought i could fix it using nitro-cloudflare-dev
.
In general the package works, but also shows that the useFetch
on SSR does not really triggers a request.
Base component
API Route: /server/api/proxy.ts
Results
1) When calling "GET https://example.com/api/proxy" i got the whole object of the cloudflare context as response.
2) When calling "GET https://example.com" and therefor trigger the component rendering, i got shown nothing
on my page. So the event.context.cloudflare
is not set on SSR request.
----------
So my only idea for fix that is by calling my api, from within my api by check (e.g. by header) from where the request is triggered.
Like:
While the component would look like:
why wouldn't you defineCachedEventHandler and e.g. the CF KV store for caching?
CF KV-Store has limits on free-plan. Even if im sure im not reaching this limits, CF cache does not have any limits.
The response i want to cache, is a json which represents the structure of my nuxt page (headless cms). Such headless CMS's or other headless providers often has limits on requests / traffic, i try to prevent to call them wherever i can.
Instead i use webhooks (e.g. when a page is changed in the CMS) to call the CF API to flush the cache for the specific api path.
E.g. (
example.com/about-us
) triggers the api call example.com/api/proxy/cms/about-us
=> this response is cached by CF.
A plus: If cloudflare responde with a cache hit, as far as i saw it correctly, your daily worker request limits does not increase as well.fair point. though worker subrequests shouldn't count either IIRC
nevertheless, I see you point. might be worth raising an issue in the nitro repository for a way to opt out from emulating
I found out a few things while reading through various Cloudflare docs and Github issues now.
First of all: Normally CF-Workers (or pages, which are basically workers) can cache responses using "fetch": https://developers.cloudflare.com/workers/examples/cache-using-fetch/
Regarding the suggestion of
defineCachedEventHandler
: There is currently an issue (https://github.com/unjs/nitro/issues/2124) which topic is to enable the CacheStorage in Cloudflare Worker environments (https://developers.cloudflare.com/workers/runtime-apis/cache/#accessing-cache)
What would make the internal cache-fetch then unnecessary, since defineCacheEventHandler takes care of the caching by using the CF cache directly.
Anyways i think even if nitro
supports it, the $fetch
within a nuxt
application is still the problem.
Without the cloudflare context in such an handler, we are not able to make use of the global caches.default
of cloudflare, since we need the request and ctx to create new cache entries:
From nuxt docs:
TLDR; So it is an nuxt-issue, not a nitro issue, or am i wrong?
@pi0 i hope it is fine i ping you here, since you are involved nearly in every issue and discussion regarding nuxt/nitro and cf-environments i found so far 😄Cloudflare Docs
Cache using fetch · Cloudflare Workers docs
Setting the cache level to Cache Everything will override the default cacheability of the asset. For time-to-live (TTL), Cloudflare will still rely on …
GitHub
route caching using CacheStorage · Issue #2124 · unjs/nitro
(context, pinged by @Atinux asked about this possibility also #1982 by @ManasMadrecha) For cloudflare and platforms that provide a CacheStorage instance, we might allow this caching method instead ...
Cloudflare Docs
Cache · Cloudflare Workers docs
Control reading and writing from the Cloudflare global network cache.
So, i found a workaround for me:
useCloudflareCache