Open CallumBoase opened 6 months ago
We'll need to deal with https://github.com/CallumBoase/plasmic-supabase/issues/7 in order to support SSG / ISR using plasmic-supabase components
Discovered that useSWR() does actually populate the query cache once issue described in https://github.com/CallumBoase/plasmic-supabase/issues/7 is temporarily nullified.
Steps to reproduce:
./utils/supabase/component.ts
to remove all logic for fetching cookies or local storage. New contents:
import { createBrowserClient } from '@supabase/ssr'
export default function createClient() { //Create the supabase client like normal const supabase = createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, );
return supabase;
};
(this obviously breaks the ability to fetch the session and run authenticated API calls to Supabase, it's just for testing)
3. run `npm run build` then `npm pack` to create a local tarball of your dev version
4. Create a plasmic project, and follow the basic installation instructions (publish to github, download repo to local machine, run npm install, add .env.local with your supabase credentials)
5. Install plasmic-supabase from your local tarball
6. Init the plasmic-supabase components, start local dev server, configure custom app host
7. From Plasmic studio: Add `SupabaseProvider` to your new app's home page using Plasmic user interface and configure it to pull data from a non-rls protected table. JSON.stringify the data from the SupabaseProvider onto the page into a text element.
8. in your test plasmic projects `[[...catchall]].tsx` file, inside `getStaticProps`, after `const queryCache = await extractPlasmicQueryData....` add this line
```typescript
console.log(JSON.stringify(queryCache))
localhost:3000
to view your locally running app. in terminal, you will NOT get any errors from react-ssr-prepass in your dev server terminal (ie you won't get the errors described
https://github.com/CallumBoase/plasmic-supabase/issues/7). This is because we aren't using window or document objects when Plasmic runs react-ssr-prepass during getStaticProps()
, so the data fetch works on the server.
You will see in terminal a console.log of the query cache from when getStaticProps
ran. You should see the data that you fetch using the SupabaseProvider
in here, even though it wasn't fetched inside usePlasmicQueryData
.
However, you will see a hydration error in the browser (cause unknown at this stage)Troubleshooting previous comment, why we get hydration error on pages with a SupabaseProvider even when you've adjusted plasmic-supabase/utils/supabase/component.ts to not use window or cookies and therefore not cause react-ssr-prepass to error:
Info 1: tried transitioning a development version of plasmic-supabase component SupabaseProvider to use useMutablePlasmicQueryData
in place of useSWR
and using that in a test project. Still get hydration errors
Info 2:
In a test plasmic project (with or without plasmic-supabase installed) create a new code component with the basics of fetching similar to SupabaseProvider
import { useMutablePlasmicQueryData } from "@plasmicapp/query";
import { DataProvider } from "@plasmicapp/loader-nextjs";
import {createBrowserClient as createClient} from '@supabase/ssr'
export function SimpleSupabase({ children }: { children: React.ReactNode }) {
const { data } = useMutablePlasmicQueryData('/simpleSupabase', async () => {
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
const { data, error } = await supabase.from('country').select('*');
//random num between 1 and 19
const randomNum = Math.floor(Math.random() * 19) + 1;
//simulate delay
await new Promise(resolve => setTimeout(resolve, 3000));
if(error) throw error;
return data[randomNum];
});
return (
<>
{data && (
<DataProvider name="SimpleSupabase" data={data}>
{children}
</DataProvider>
)}
</>
);
}
Then register that in plasmic-init.ts
PLASMIC.registerComponent(SimpleSupabase, {
name: "SimpleSupabase",
providesData: true,
props: {
children: "slot"
}
})
This works as expected! Data is cached on the server, and 3 seconds later you see the stale data revalidated with a new random country
Info 3:
Using useSWR
in place of useMutablePlasmicQueryData
does not work. Data is not fetched during server side render
import useSWR from "swr";
import { DataProvider } from "@plasmicapp/loader-nextjs";
import {createBrowserClient as createClient} from '@supabase/ssr'
export function SimpleSupabase({ children }: { children: React.ReactNode }) {
const { data } = useSWR('/simpleSupabase', async () => {
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
const { data, error } = await supabase.from('country').select('*');
//random num between 1 and 19
const randomNum = Math.floor(Math.random() * 19) + 1;
//simulate delay
await new Promise(resolve => setTimeout(resolve, 3000));
if(error) throw error;
return data[randomNum];
});
return (
<>
{data && (
<DataProvider name="SimpleSupabase" data={data}>
{children}
</DataProvider>
)}
</>
);
}
Next steps:
SupabaseProvider
works fully with useMutablePlasmicQueryData
including optimistic updatesSupabaseProvider
until hydration error is encountered?Gradually adding functionality from SupabaseProvider
into SimpleSupabase
component to identify where hydration errors occur & to check if all behaviour works
Important note: optimistic operations work! This means we should be able to transition the product PlasmicSupabase
to use useMutablePlasmicQueryData
Next steps: continue adding parts of PlasmicSupabase
component until hydration error is found.
Copy-pasted SupabaseProvider
and all it's dependencies from plasmic-supabase into a sample app
transitioned createClient()
inside SupabaseProvider
to the simplified one
import { createBrowserClient} from '@supabase/ssr';
//An unrealistically simplified createClient without ref to cookies or local storage
const createClient = () => createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
And transitioned useSWR
in SupabaseProvider
into useMutablePlasmicQueryData
When running the example app with pages containing non-rls protected api calls to Supabase via SupabaseProvider
, it seems to support server side data prefetching and caching as expected, and there's no hydration errors!
(exact setup here).
Next steps: try that exact setup in the plasmic-supabase repo instead and see if something about having plasmic-supabase as an external dependency is causing the hydration issue
Edit: the simple SupabaseProvider directly used DOES seem to be working with SSG and ISR But making equivalent changes and either importing SupabaseProvider from install, or a very similar local version, neither seem to do ISR or SSG - the server html always says No data and validating (I think).
Need to confirm this behaviour
This direct usage of SupabaseProvider directly from the project (as opposed to installed from plasmic-supabase) works
The exact same SupabaseProvider installed from local dev tgz of Plasmic-Supabase (external dependency) DOES fail for some reason! We get hydration errors again
Trying to bundle plasmic-supabase using more complete bundling with Vite instead of basic typescript bundling to see if that fixes the hydration error.
Initial attempt here: https://github.com/CallumBoase/plasmic-supabase-new-bundling-test And used in this branch: https://github.com/CallumBoase/Plasmic-supabase-test-130624-0945hrs/tree/plasmic-supabase-new-bundling-test
Result from initial test: no hydration errors, but the data is not available in react-ssr-prepass and the component is not server rendered either!
Tried bundling with same configuration as @plasmicapp/pkgs/sanity-io
It worked with SupabaseProvider: https://github.com/CallumBoase/plasmic-supabase-bundled-like-plasmic including
Next steps:
Context
The Plasmic docs on data-fetching code components suggest using the function
usePlasmicQueryData
to wrap any data queries.This enables data queries to be pre-rendered during render, so that your site can be pre-generated and/or cached with results of queries data using Static Site Generation and/or Incremental Static Regeneration.
When using plasmic to generate a nextjs app with the loader API (as opposed to codegen), ISR works by default if you've used
usePlasmicQueryData
to wrap data queries, due to the getStaticProps function usingextractPlasmicQueryData
(see this default catchall page).Problem
All data queries in plasmic-supabase avoid use of
usePlasmicQueryData
, and instead useuse-swr
.This was done because, despite
usePlasmicQueryData
being a lightweight wrapper arounduse-swr
, it did not seem to support optimistic updates, which is a key functionality of plasmic-supabase.Solution
Figure out how to fetch data in plasmic-supabase in a way supports both SSG / ISR, and optimistic updates. Ideally it should work out-of-the-box with plasmics default catchall page generated when you publish a Plasmic app to nextjs using the loader API, however it could be OK to provide clear instructions to users on how they adjust the catchall page to support SSG and/or ISR if needed.