pacocoursey / next-themes

Perfect Next.js dark mode in 2 lines of code. Support System preference and any other theme with no flashing
https://next-themes-example.vercel.app/
MIT License
4.98k stars 179 forks source link

Support themed SSG #67

Closed eric-burel closed 2 years ago

eric-burel commented 2 years ago

Hi, I haven't had the chance to test this library but I've checked the README quickly. It seems you cannot yet support themed SSG. I've been working on this subject a lot last year, and the introduction of Middlewares finally provided a solution to this.

The use case is very similar to A/B testing, see https://github.com/vercel/examples/tree/main/edge-functions/ab-testing-simple

To sum it up:

I've written an article to show how it scales to even more parameters: https://blog.vulcanjs.org/render-anything-statically-with-next-js-and-the-megaparam-4039e66ffde. You can skip to the code demo, I show theming and multi-tenancy: https://github.com/VulcanJS/vulcan-next/blob/devel/src/pages/vn/examples/%5BM%5D/megaparam-demo.tsx I call this a "hidden param trick" or "Megaparam".

Hope you'll enjoy!

pacocoursey commented 2 years ago

Hey, that's a good idea! You can definitely avoid injecting the render-blocking inline script with middleware and this technique.

However, generating two versions of each page ahead of time just to change the theme seems a bit overkill when we have CSS variables, and next-themes already solves the flash. If you have 200 pages, you just doubled that to 400 (likely with an associated double in build time...). Next-themes scales more like next/image does: moving a tiny amount of work to runtime so that you can scale infinitely.

Next-themes already supports all Next.js rendering techniques, including SSG pages (through forced theme, or by synchronously reading from localStorage via injected script)

eric-burel commented 2 years ago

Nice, I'll close the issue but keep it as a reference. I've reread the README, so the hydratation issue is only affecting the very scenario where you allow theme switch via a button? This section https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch was not 100% clear to me at first read, so it sounds like SSG is not fully supported. But your answer makes it clearer, I've seen this blocking script pattern on Vercel dashboard as well. (btw: awesome job :))

eric-burel commented 2 years ago

Btw the typical use case for prerendered theming is multi-tenancy, because you have only one theme per organization, and a few organizations with a lot of users, so it's worth rendering 1 theme for each organization. You can use ISR, so the first user of the organization pays the rendering time and you avoid the upfront cost at build-time. I agree it makes less sense at user level like dark/light theme.