Closed CallumBoase closed 3 months ago
Draft new [...catchall].tsx
page that is currently being trialled
This changes behaviour:
maybeFetchComponentData()
) is done client-side (so the page itself loads much faster, but shows a "Loading..." message when necessary// ./pages/[...catchall].tsx
/*
Catchall page that runs for every page EXCEPT /, /login, and /public/*
These pages are login protected by default
The logic for checking authorization & where to redirect if a user is not authorized is controlled
by @/authorization-settings.ts.
The authorization-settings.ts file should export:
- authorizationCheckFunction: a function that returns true if the user is authorized to view the page
- loginPagePath: where to redirect to if authorization fails eg '/login'
The routes that render through this page are rendered on-demand (getServerSideProps instead of getStaticProps)
because they are login protected. This ensures that the user's session is checked on every request
and avoids login-protected pages being cached and related issues.
This pages is a modified various of the standard Plasmic NextJS loader API catchall page.
Pages created in Plasmic studio will render using this catchall if it's:
Page Settings -> URL path does NOT start with '/public/' and is not "/" or "/login"
*/
import type { GetServerSideProps } from "next";
import { createClient } from 'plasmic-supabase/dist/utils/supabase/server-props'
import * as React from "react";
import {
PlasmicComponent,
PlasmicRootProvider,
} from "@plasmicapp/loader-nextjs";
import Error from "next/error";
import { useRouter } from "next/router";
import { PLASMIC } from "@/plasmic-init";
import useSWR from "swr";
import { authorizationCheckFunction, loginPagePath } from "@/authorization-settings";
export default function PlasmicLoaderPage(props: {
plasmicPath: string;
}) {
const router = useRouter();
//Fetch the component (page) data from Plasmic and cache it with SWR
//Note that when navigating between [[...catchall]].tsx and this page
//A warning from Plasmic will appear in console https://github.com/plasmicapp/plasmic/blob/7117b4c2de9e89f4435db9efa0cba6a00012c297/packages/loader-react/src/loader-shared.ts#L498
//Because maybeFetchComponentData will fetch designs with query string parameter browserOnly=true here
//But browserOnly=false from [[...catchall]].tsx
//Because fetching of Plasmic componet data is happening client side here, but server side in [[...catchall]].tsx
//This does not appear to matter since the referenced file above seems to gracefully handle this case
//However if the error could be removed by some refactor, it would be ideal
const plasmicComponentFetcher = React.useCallback(async () => {
return await PLASMIC.maybeFetchComponentData(props.plasmicPath);
}, [props.plasmicPath]);
const { data: plasmicData, error, isValidating } = useSWR(
`plasmicData_${props.plasmicPath}`,
plasmicComponentFetcher
);
//Render the error page if there is an error
if(error) {
return <Error statusCode={500} />;
}
//Render a loading message if the data is still loading
if(isValidating && !plasmicData) {
return <div>Loading...</div>;
}
//Render a 404 page if the page is not found in Plasmic
if ((!isValidating && (!plasmicData || plasmicData.entryCompMetas.length === 0))) {
return <Error statusCode={404} />;
}
//Extract the page meta data from the Plasmic data
const pageMeta = plasmicData!.entryCompMetas[0]
//Render the Plasmic component (page)
return (
<PlasmicRootProvider
loader={PLASMIC}
prefetchedData={plasmicData!}
prefetchedQueryData={{}}
pageParams={pageMeta.params}
pageQuery={router.query}
>
<PlasmicComponent component={pageMeta.displayName} />
</PlasmicRootProvider>
);
}
//This runs on the server while rendering
//Unlike the pages in the root directory, we run this every time the page is requested with no cache
//This is appropriate because these pages are login protected and only work with a valid session
//We also need to recheck each time the page is requested to ensure the user is still authenticated
export const getServerSideProps: GetServerSideProps = async (context) => {
//Get the catchall parameter from the page context
const { catchall } = context.params ?? {};
//Get the path of the current page
let plasmicPath = typeof catchall === 'string' ? catchall : Array.isArray(catchall) ? `/${catchall.join('/')}` : '/';
//Determine if the user is authorized to view this page
const supabase = createClient(context);
const { data: { user } } = await supabase.auth.getUser();
const isAuthorized = authorizationCheckFunction(plasmicPath, user);
if(isAuthorized !== true) return {
redirect: {
destination: loginPagePath,
permanent: false,
}
}
//We don't try and fetch the plasmic component data or data on the page here, because getServerSideProps does not cache
//Therefore we would run this every time without cache, causing slow page navigation
//Instead, we do that client-side and cache results with SWR (see above)
return { props: { plasmicPath } };
}
After further experemintation, the sluggish page load speed persists even with the above changes.
This will be addressed by changing to use of middleware to login protect pages see https://github.com/CallumBoase/plasmic-supabase/pull/22
CONTEXT: In version
0.1.0
intructions were added to create a[...catchall].tsx
page in the root directory which makes use ofgetServerSideProps()
instead of the standardgetStaticProps()
to:extractPlasmicQueryData
PROBLEM