supabase-js
supabase-js copied to clipboard
Next.js Cache (beta)
Improve documentation
Link
https://supabase.com/docs/reference/javascript/select
Describe the problem
See the release notes here: https://nextjs.org/blog/next-13-2#nextjs-cache
It is not clear how to take advantage of this feature when fetching data with the supabase.js client.
Describe the improvement
Describe how to set the desired cache duration to enable ISR at the component level.
Additional context
None
You can pass a custom fetch function into supabase and it works.
First create a fetch factory function that takes next cache properties as parameters:
// utils/cache.ts
export const createFetch =
(options: Pick<RequestInit, "next" | "cache">) =>
(url: RequestInfo | URL, init?: RequestInit) => {
return fetch(url, {
...init,
...options,
});
};
Then in your RSC:
import { createFetch } from "@/utils/cache";
const supabase = createServerComponentClient({ cookies }, {
options: {
global: {
fetch: createFetch({
cache: "no-store"
})
}
}
});
"Good to know: cookies() is a Dynamic Function whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into dynamic rendering at request time."
Any way we get around this?
Edit: This might be helpful
"Good to know: cookies() is a Dynamic Function whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into dynamic rendering at request time."
Any way we get around this?
Edit: This might be helpful
Yes. Just use the regular supabase client. Create a wrapper like above using only Supabase createClient
and service key.
The pre-requisite is that you don't use any auth on the server in that case as that requires the page to be SSR/dynamic rendered.
Great snippet! Is anyone able to tell me why the first request isn't getting cached? It looks pretty identical to the third one to me. I'm using a regular refresh with F5 in next dev.
Code:
const supabase = createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!,
{
global: {
fetch: createFetch({
next: {
revalidate: 1800,
},
}),
},
}
);
const { count: items } = await supabase
.from('sheetsItem')
.select('*', { count: 'estimated', head: true })
.eq('active', true);
const { data: itemsMarketplace } = await supabase.rpc('count_distinct_items');
const { count: spreadsheets } = await supabase
.from('sheetsSheet')
.select('*', { count: 'exact', head: true })
.eq('active', true);
Logs:
GET /search/spreadsheet200 in 9540ms
│ HEAD https://api.example.com/rest/v1/sheetsItem?select=*&active=eq.true 206 in 6898ms (cache: SKIP)
│ │ Cache missed reason: (cache-control: no-cache (hard refresh))
│ │ HEAD https://api.example.com/rest/v1/sheetsSheet?select=*&active=eq.true 200 in 2ms (cache: HIT)
│ │ POST https://api.example.com/rest/v1/rpc/count_distinct_items 200 in 0ms (cache: HIT)
Great snippet! Is anyone able to tell me why the first request isn't getting cached? It looks pretty identical to the third one to me. I'm using a regular refresh with F5 in next dev.
Code:
const supabase = createClient<Database>( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_KEY!, { global: { fetch: createFetch({ next: { revalidate: 1800, }, }), }, } ); const { count: items } = await supabase .from('sheetsItem') .select('*', { count: 'estimated', head: true }) .eq('active', true); const { data: itemsMarketplace } = await supabase.rpc('count_distinct_items'); const { count: spreadsheets } = await supabase .from('sheetsSheet') .select('*', { count: 'exact', head: true }) .eq('active', true);
Logs:
GET /search/spreadsheet200 in 9540ms │ HEAD https://api.example.com/rest/v1/sheetsItem?select=*&active=eq.true 206 in 6898ms (cache: SKIP) │ │ Cache missed reason: (cache-control: no-cache (hard refresh)) │ │ HEAD https://api.example.com/rest/v1/sheetsSheet?select=*&active=eq.true 200 in 2ms (cache: HIT) │ │ POST https://api.example.com/rest/v1/rpc/count_distinct_items 200 in 0ms (cache: HIT)
Caching works different in Next.js dev-mode and production