Skip to content
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

[NEXT-643] FOUC using CSS-in-JS libraries in appDir through useServerInsertedHTML #44125

Open
1 task done
mghizzo opened this issue Dec 18, 2022 · 15 comments
Open
1 task done
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team.

Comments

@mghizzo
Copy link

mghizzo commented Dec 18, 2022

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 22.2.0: Fri Nov 11 02:03:51 PST 2022; root:xnu-8792.61.2~4/RELEASE_ARM64_T6000
Binaries:
Node: 16.16.0
npm: 8.11.0
Yarn: 1.22.19
pnpm: N/A
Relevant packages:
next: 13.0.8-canary.0
eslint-config-next: 13.0.6
react: 18.2.0
react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue

https://github.com/mghizzo/next-reproduction-app

To Reproduce

Start the bug reproduction project and just navigate to http://localhost:3000 to see FOUC, you can also disable javascript on the page to ensure that styles which should be injected are not there.

Describe the Bug

Using useServerInsertedHTML inside a component won't inject result in the head if there's no <head> tag.
You can temporarily fix this issue by using head tag somewhere (head file if you have one or just put a <head /> in the Root Layout.
I also found a commit which was meant for a fix but it was then reverted.

Expected Behavior

It is expected that the result of useServerInsertedHTML gets injected inside the head.

Which browser are you using? (if relevant)

Google Chrome 108.0.5359.124 (ARM64)

How are you deploying your application? (if relevant)

No response

NEXT-643

@mghizzo mghizzo added the bug Issue was opened via the bug report template. label Dec 18, 2022
@jesko-plitt
Copy link

jesko-plitt commented Dec 27, 2022

@mghizzo Thank you so much for opening this issue. Especially for your temporary solution.

I am experiencing the same problems. Using styled-components and following the instructions in https://beta.nextjs.org/docs/styling/css-in-js#styled-components leads to layout shifts. Adding the <head /> to my app/layout.tsx fixed that.

I have no idea if that is expected behavior or not. If it is expected it would be nice to add this to the documentation.

@IonelLupu
Copy link

IonelLupu commented Jan 5, 2023

@jesko-plitt I already have the "< head >" tag in my RootLayout and I still get this issue (using AntDesign v5). It was always there in Next.js 13 projects. Here is my app/layout.tsx file:

export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html lang="en">
            <head />
            <body>
                <ThemeProvider>
                    {children}
                </ThemeProvider>
            </body>
        </html>
    )
}

@mghizzo
Copy link
Author

mghizzo commented Jan 5, 2023

@IonelLupu This is my solution in Nextjs 13 with App Directory & Ant Design 5

layout.tsx

"use client";
import { ConfigProvider, theme } from "antd";
import { useEffect, useState } from "react";
import { createCache, extractStyle, StyleProvider } from "@ant-design/cssinjs";
import { useServerInsertedHTML } from "next/navigation";
import "styles/globals.css";
import "antd/dist/reset.css";
import itIT from "antd/locale/it_IT";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="it">
      <head />
      <body>
        <StyleProviderLayout>{children}</StyleProviderLayout>
      </body>
    </html>
  );
}

function StyleProviderLayout({ children }: { children: React.ReactNode }) {
  const [cache] = useState(() => createCache());

  const render = <>{children}</>;

  useServerInsertedHTML(() => {
    return <script
        dangerouslySetInnerHTML={{
          __html: `</script>${extractStyle(cache)}<script>`,
        }}
      />;
  });

  if (typeof window !== "undefined") {
    return render;
  }

  return <StyleProvider cache={cache}>{render}</StyleProvider>;
}

Edit: found a workaround so that we don't need an external library anymore

@devagrawal09
Copy link
Contributor

@mghizzo I am facing this issue with the pages directory, ant design is causing FOUC, how did you fix it?

@IonelLupu
Copy link

@devagrawal09 check this issue: ant-design/ant-design#39891. Someone also proposed a fix on the Next.js side: #44015. Waiting to be merged

@devagrawal09
Copy link
Contributor

@IonelLupu all the examples are with the app directory, I'm on the pages directory

@timneutkens timneutkens added the linear: next Confirmed issue that is tracked by the Next.js team. label Feb 27, 2023
@timneutkens timneutkens changed the title FOUC using CSS-in-JS libraries in appDir through useServerInsertedHTML [NEXT-643] FOUC using CSS-in-JS libraries in appDir through useServerInsertedHTML Feb 27, 2023
@dreamstyle
Copy link

I have the same issue with Next.js 13 (pages directory) + Ant Design v5!
Did anyone get a solution?

@devagrawal09
Copy link
Contributor

I have the same issue with Next.js 13 (pages directory) + Ant Design v5! Did anyone get a solution?

No I pretty much gave up and moved to Tailwind

@bombillazo
Copy link

So, no solution for Next 13 (pages) + Ant Design SSR?

@tobiasriemenschneider
Copy link

So, no solution for Next 13 (pages) + Ant Design SSR?

This would be a bummer, considering that app dir is still in beta and pages still the default.

@ctgsjrgl
Copy link

Same here! Did anyone get a solution?

@HasanMothaffar
Copy link

Same issue here with Next.js 13 (pages directory) and Ant Design 5. Is there any example for the pages directory?

@jason-ku-8313
Copy link

Hey guys,

I discovered that the antd team offers two solutions on their official page: https://ant.design/docs/react/customize-theme#server-side-render-ssr.
The second solution, "Whole export" worked for me 👍
All I had to do was follow this example project to resolve the issue: https://github.com/ant-design/create-next-app-antd

@dreamstyle @bombillazo @ctgsjrgl @HasanMothaffar

@PandukaNandara
Copy link

Adding hashPriority="high" to StyleProvider is worked for me. This is how I did.

"use client";
import { ConfigProvider, theme } from "antd";
import React, {
  createContext,
  FC,
  PropsWithChildren,
  useContext,
  useMemo,
  useState,
} from "react";

import { StyleProvider, createCache, extractStyle } from "@ant-design/cssinjs";
import { useServerInsertedHTML } from "next/navigation";

const ThemeContext = createContext<{  }>({

} as any);

// eslint-disable-next-line react-hooks/rules-of-hooks
export const useTheme = () => useContext(ThemeContext);

const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
  const [cache] = useState(() => createCache());
  useServerInsertedHTML(() => {
    return (
      <style
        id="antd-style"
        dangerouslySetInnerHTML={{
          __html: extractStyle(cache, true),
        }}
      />
    )
  })


  return (
    <StyleProvider cache={cache} hashPriority="high">
      <ConfigProvider
        direction="ltr"
        theme={{
          algorithm: mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
          token: {
            colorPrimary: "#3f7291",
          },
        }}
      >
        <ThemeContext.Provider
          value={{}}
        >
          {children}
        </ThemeContext.Provider>
      </ConfigProvider>
    </StyleProvider>
  );
};

export default ThemeProvider;

@monolithed
Copy link

@PandukaNandara, the problem with this approach is that the Time to First Byte (TTFB) will be 2-3 seconds. Your users won't be able to get styles until the server compiles them in runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team.
Projects
None yet
Development

No branches or pull requests