supabase-js
supabase-js copied to clipboard
`fetch` override does not go well with Next.js' caching
Bug report
- [x] I confirm this is a bug with Supabase, not with my own application.
- [x] I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
To assign cache tags to control Next.js' data caching, Supabase's custom fetch override should be used. Referred https://github.com/supabase/supabase-js/issues/725#issuecomment-1578811299
However there seems to be some incompatibility present; Next.js patched fetch
API does not seem to be applied to Supabase's fetch, resulting data cache completely not to work.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
There is a sample project for reproduction.
- Build and deploy sample project
- A supabase project and deployment target should've set up; I used CloudFlare
- Data caching and API such as
revalidateTag
from Next.js does not work properly, compared to direct usage offetch
API in the test code
Expected behavior
Whether fetch
is used directly or via Supabase API the data cache should be used.
Screenshots
If applicable, add screenshots to help explain your problem.
System information
- Version of supabase-js: 2.38.4
- Version of Node.js: v20.2.0
- Version of Next.js: v13.5.4
Additional context
Add any other context about the problem here.
I remember I had checked this in the past and it was using the correct fetch. We'll investigate. In the meantime, you can pass the fetch
object to the createClient
method: https://supabase.com/docs/reference/javascript/initializing?example=custom-fetch-implementation
I can't reproduce this on the sample project with npm run dev
.
and deployment target should've set up; I used CloudFlare
Can you clarify what this means? Are you deploying the Next.js project to CF Workers? I'm not familiar with Next.js-isms.
Yeah, I used CF workers and pages for deployment. I wonder if the issue is specific to CF environment + Next.js edge runtime or not.
As a workaround I copy-pasted some of internal postgrest-js
code (like this) and made supabaseNextCompatFetch
wrapper function.
Passing global fetch object to the createClient method did not work but the method above did. Quite confusing.
Not sure if this is related, but I have the opposite issue: I can't get rid of the cache...
@susemeee Does your supabase client wrapper support setting tags on a query basis?
I'm having the same issue on my project. Fetching data with the supabase server client causes next to not use the data cache at all. But if I manually create the url and use fetch
directly then the cache works fine.
@thorwebdev's solution didn't work.
I'm having the same issue on my project. Fetching data with the supabase server client causes next to not use the data cache at all. But if I manually create the url and use
fetch
directly then the cache works fine. @thorwebdev's solution didn't work.
How did you write the custom fetch?
this worked for me in dev mode, haven't tried in production on nextjs 14.x can cache supabase queries using tags.. it sets cache options per supabase-client and not per request. but better than nothing.
export const createClientWithCache = ( cacheOptions: any = {} ) => {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
/*
// got middleware for setAll..
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => {
cookieStore.set(name, value, options);
});
} catch (error) {
// The `set` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
*/
},
global: {
fetch: (url: any, options = {}) => {
return fetch( url, { ...options, ...cacheOptions });
}
}
},
);
};
// usages:
// import { createClientWithCache } from "@/utils/supabase/server";
// ..
// const supabase = createClientWithCache({
// cache: 'force-cache', // or 'no-cache' // didn't work without it
// next: {
// //revalidate: 30,
// tags: ['get-koi'],
// }
// });
//
// const { data, error } = await supabase
// .from('kois')
// .select()
// .eq('id', id)
// ..
//
// revalidateTag( 'get-koi' )
I get the same error when running SSR in an angular environment.