Skip to content

[BUG] Nesting Layouts with next-themes #511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
NavOrange opened this issue Mar 27, 2025 · 13 comments
Open

[BUG] Nesting Layouts with next-themes #511

NavOrange opened this issue Mar 27, 2025 · 13 comments
Labels
bug Something isn't working waiting for feedback

Comments

@NavOrange
Copy link

NavOrange commented Mar 27, 2025

Describe the bug

I'm encountering an error in the preview when using nested layouts to handle multiple languages alongside next-themes (include inline script -> error)

repo: https://github.com/NavOrange/nesting-layouts-with-next-themes

Image Image

__name(m3, "m3");

This code issue only appears after the opennextjs-cloudflare build process, and it seems the code has been formatted as well.

@opennextjs/cloudflare@0.5.12, inline code is also formatted, but no unexpected code appears.

Steps to reproduce

  1. clone code
  2. cd nesting-layouts-with-next-themes && pnpm install
  3. pnpm preview
  4. open browser
  5. go to http://localhost:8787/en
  6. open console

Expected behavior

No unexpected code

@opennextjs/cloudflare version

^0.6.0

Wrangler version

^4.5.0

next info output

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 24.3.0: Thu Jan  2 20:22:00 PST 2025; root:xnu-11215.81.4~3/RELEASE_X86_64
  Available memory (MB): 16384
  Available CPU cores: 12
Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.6.2
Relevant Packages:
  next: 15.2.4 // Latest available version is detected (15.2.4).
  eslint-config-next: N/A
  react: 19.0.0
  react-dom: 19.0.0
  typescript: 5.8.2
Next.js Config:
  output: N/A

Additional context

No response

@NavOrange NavOrange added bug Something isn't working triage labels Mar 27, 2025
@vicb
Copy link
Contributor

vicb commented Mar 27, 2025

I can not reproduce locally (the behavior is similar with next dev)

Image

@NavOrange
Copy link
Author

NavOrange commented Mar 27, 2025

@vicb Sorry, I missed go to http://localhost:8787/en

Additionally, everything works fine if I don't use nested layouts.

@eposha
Copy link

eposha commented Mar 27, 2025

same issue

It happens in production. When deploying to cloudflare.

@vicb You need to go to the page with the error and do a refresh

Image

@vicb
Copy link
Contributor

vicb commented Apr 1, 2025

Note: The __name(...) call is added by the ESBuild pass of wrangler (see cloudflare/workers-sdk#6901).

@vicb vicb removed the triage label Apr 1, 2025
@vicb
Copy link
Contributor

vicb commented Apr 1, 2025

The cause cause of the issue here seems to be script.toString() in next-themes.

Would would be nice is to open an issue on the repo and ask for the value to be inlined at build time.

What happens with the Cloudflare adapter is that we bundle the code into a single JS file for deployment using ESBuild. ESBuild add those __name(...) calls - __name is defined at the top level to preserve the name of functions/classes when bundling and/or minifying.

@NavOrange
Copy link
Author

The cause cause of the issue here seems to be script.toString() in next-themes.

Would would be nice is to open an issue on the repo and ask for the value to be inlined at build time.

What happens with the Cloudflare adapter is that we bundle the code into a single JS file for deployment using ESBuild. ESBuild add those __name(...) calls - __name is defined at the top level to preserve the name of functions/classes when bundling and/or minifying.

Thank you for your work on this! However, it seems like this doesn't explain why the issue only arises when nested layouts are used.

@dario-piotrowicz
Copy link
Contributor

dario-piotrowicz commented Apr 4, 2025

A potential fix for this: pacocoursey/next-themes#349
(let's see what the next-themes folks reply 🙂🤞)

@Shobhit-Nagpal
Copy link

The cause cause of the issue here seems to be script.toString() in next-themes.
Would would be nice is to open an issue on the repo and ask for the value to be inlined at build time.
What happens with the Cloudflare adapter is that we bundle the code into a single JS file for deployment using ESBuild. ESBuild add those __name(...) calls - __name is defined at the top level to preserve the name of functions/classes when bundling and/or minifying.

Thank you for your work on this! However, it seems like this doesn't explain why the issue only arises when nested layouts are used.

just faced this issue and i'm not using nested layouts yet still facing this error. everything works fine in dev but when i preview it, the site shows up for a split second and then it's blank white

@eposha
Copy link

eposha commented Apr 24, 2025

I found a solution that fixes the flickering. It won't remove the console error itself, but at least there will be no flickering.

I just added a script from next-themes that causes the error directly in the layout inside ThemeProvider

const fixedThemeBlindScript = `( (attribute, storageKey, defaultTheme, forcedTheme, themes, value, enableSystem, enableColorScheme) => {
                const el = document.documentElement;
                const systemThemes = ['light', 'dark'];
                function updateDOM(theme) {
                    const attributes = Array.isArray(attribute) ? attribute : [attribute];
                    attributes.forEach( (attr) => {
                        const isClass = attr === 'class';
                        const classes = isClass && value ? themes.map( (t) => value[t] || t) : themes;
                        if (isClass) {
                            el.classList.remove(...classes);
                            el.classList.add(value && value[theme] ? value[theme] : theme);
                        } else {
                            el.setAttribute(attr, theme);
                        }
                    }
                    );
                    setColorScheme(theme);
                }
                function setColorScheme(theme) {
                    if (enableColorScheme && systemThemes.includes(theme)) {
                        el.style.colorScheme = theme;
                    }
                }
                function getSystemTheme() {
                    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
                }
                if (forcedTheme) {
                    updateDOM(forcedTheme);
                } else {
                    try {
                        const themeName = localStorage.getItem(storageKey) || defaultTheme;
                        const isSystem = enableSystem && themeName === 'system';
                        const theme = isSystem ? getSystemTheme() : themeName;
                        updateDOM(theme);
                    } catch (e) {//
                    }
                }
            }
            )("class", "theme", "system", null, ["light", "dark"], null, true, true);`;

or minified version

const fixedThemeBlindScript = `((e,t,s,l,c,a,r,i)=>{let m=document.documentElement,n=["light","dark"];function h(t){let s=Array.isArray(e)?e:[e];s.forEach(e=>{let s="class"===e,l=s&&a?c.map(e=>a[e]||e):c;s?(m.classList.remove(...l),m.classList.add(a&&a[t]?a[t]:t)):m.setAttribute(e,t)}),o(t)}function o(e){i&&n.includes(e)&&(m.style.colorScheme=e)}function d(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}if(l)h(l);else try{let u=localStorage.getItem(t)||s,f=r&&"system"===u,y=f?d():u;h(y)}catch(g){}})("class","theme","system",null,["light","dark"],null,!0,!0);`;

So just add this script into your code

<ThemeProvider
  attribute="class"
  defaultTheme="system"
  enableSystem
  disableTransitionOnChange          
>

  <script>{fixedThemeBlindScript}</script>

   {children}
</ThemeProvider>

@dario-piotrowicz
Copy link
Contributor

Quick solution for the issue, you can use the latest wrangler release and set keep_names to false, with that the issue goes away 🙂 (and so far I haven't noticed any other side effects in setting the flag)

@eposha
Copy link

eposha commented Apr 24, 2025

What does this flag do?

@dario-piotrowicz
Copy link
Contributor

You can see what the flag does in the wrangler changelog here: https://github.com/cloudflare/workers-sdk/releases/tag/wrangler%404.13.0

basically esbuild adds this __name function that it uses to keep the name of functions (as in the conversation above) and this flags disables that solving the issue

@vicb
Copy link
Contributor

vicb commented Apr 29, 2025

@Dario created a fix on the original repo: pacocoursey/next-themes#354

You can 👍 the PR if you are interested in getting this fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working waiting for feedback
Projects
None yet
Development

No branches or pull requests

5 participants