Closed steve-marmalade closed 1 year ago
Hey @steve-marmalade,
You've got a serious point here.
Basically, any page that depends on user cookies should be considered dynamic and cannot be statically generated.
My solution here would be to remove AuthProvider
and cookies()
from root layout altogether and include it only on pages that are supposed to be dynamic and have content exclusive to specific user.
You've given me an idea of providing example with statically generated pages. I'll add it as a resolution to this issue.
Thanks for feedback!
Awesome, glad it was helpful!
If you are looking for inspiration - I think a powerful (and challenging) use-case would be one where the page is static, except for e.g. a component in the Navbar that contains a user's profile icon. I am not sure if it's possible to have only certain components on a page be dynamic, or if the use of dynamic functions in any component on the page will case the entire page to be dynamic.
Currently I am planning to use the Firebase Javascript SDK in that case, so that the page immediately loads the static content and then is progressively enhanced with user data in a client component, but it introduces the risk that there are edge cases where the authentication state in the cookies and in the client get out of sync.
Hey @steve-marmalade,
I did experiment a while with static generation and come up with next13-typescript-static-pages example.
You can test it with a Google sign up method at next-firebase-auth-edge-static-demo
Basically, there are three options when it comes to authenticating pages in Next.js 13:
cookies
function as in herecookies
in layout (either root or nested), as in /login page layout examplecookies
directly in page.tsx
or any nested server component, as seen on the profile pageAlthough 1.
supports static page generation, 2.
and 3.
will force server-side rendering because of calling cookies()
upon rendering
Unfortunately, Next.js does not seem to support partial static generation. If your server components want to access request context at some point, they have to be rendered dynamically.
You can still achieve user-dedicated content on static pages without accessing cookies
, by rendering user components using client-side authentication.
Let me know if this answers your question. Cheers!
@awinogrodzki - thank you for the thoughtful responses and examples.
Regarding your point:
Unfortunately, Next.js does not seem to support partial static generation. If your server components want to access request context at some point, they have to be rendered dynamically.
I wonder whether you think the new Vercel Cache API changes this at all? Here's an excerpt from the intro:
Before today, developers had to choose between either fully static or fully dynamic pages.
With Next.js 13.2, we’re excited to announce the Next.js Cache (beta) and the brand-new Vercel Cache API (beta). This enables caching only part of your page as static data, while fully dynamically rendering the rest of your application, including accessing real-time and personalized data.
@steve-marmalade, thanks for the article, it's pretty interesting. I might have even found a reason for a bug I've been experiencing recently.
Key takeaway from the article is this:
// Cached until manually invalidated
fetch(`https://...`),
// Refetched on every request
fetch(`https://...`, { cache: 'no-store' }),
// Cached with a lifetime of 10 seconds
fetch(`https://...`, { next: { revalidate: 10 } }),
If we don't pass any headers to fetch
, it will be cached indefinitely.
To understand how next-firebase-auth-edge
is using fetch
, let's look at this flow chart:
The actual http fetch
call does not happen until the last step: refresh and return new token
. The refresh token step is called with specific Authorization
headers, which mean it is not cached (thankfully).
This means two things. We cannot really leverage Next Cache in a meaningful way, but we don't really need to. Token verification step is instant as soon as provided idToken is valid.
I also want to thank you. When investigating this topic I have found out, that we don't overwrite stale cookies with new ones – this means that as soon as original idToken is expired, we will make request to refresh the token each time user access the page. I will fix that today.
Cheers!
Hey there, apologies if this was self-evident to others but caught me by surprise: the current example uses
cookies()
in the root layout, which is considered a dynamic function (since the contents will only be known at request-time). As a result, it is not possible to statically generate any of the pages in the app, regardless of whether those pages use the auth context.As a workaround, I am planning to use the cookies only in the middleware, and then let client components separately handle authentication using the firebase SDK. Would be nice to avoid the network request to firebase and leverage the cookie, but I can't give up static generation.
Figured I'd share in case it was useful. Thanks again for the effort put into this library.