ant-design / cssinjs

https://ant-design.github.io/cssinjs
MIT License
235 stars 57 forks source link

NextJS 14 Flicker CSS Issue #157

Closed galihlprakoso closed 7 months ago

galihlprakoso commented 8 months ago

I think the library need to adapt NextJS 14.

'use client'

import React from 'react'
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'
import type Entity from '@ant-design/cssinjs/es/Cache'
import { useServerInsertedHTML } from 'next/navigation'

const StyledComponentsRegistry = ({ children }: React.PropsWithChildren) => {
  const cache = React.useMemo<Entity>(() => createCache(), [])
  useServerInsertedHTML(() => (
    <style id="antd" dangerouslySetInnerHTML={{ __html: extractStyle(cache, true) }} />
  ))
  return <StyleProvider cache={cache}>{children}</StyleProvider>
}

export default StyledComponentsRegistry

The flicker still happening after implementing this guide from antd design documentation. When I tried to downgrade to NextJS 13, it works. The flicker css only happens on NextJS 14.

Sarlaka commented 8 months ago

I meet the same problem too. The flicker css still happens when i use next@14.0.1 but it works well after i downgrade to next@13.5.6.

jknap commented 7 months ago

I managed to reproduce here https://github.com/jknap/antd-demo/tree/main

It works the first time. Now if you delete the node_modules and run npm install again, then you can reproduce. Downgrading to next@13.5.6 does not solve the issue in this case.

It seems that the cache returned by createCache is empty in this case. I noticed that when the cache is not empty, this method is called multiple times, and it's never called when the issue is reproduced. I am not sure what is triggering it so I could not dig more unfortunately, but the issue seems to come from there.

jknap commented 7 months ago

Ok I found the issue, it was due to a mismatch between the @ant-design/cssinjs version and the one that antd depends on. This can be fixed by forcing the same @ant-design/cssinjs version in package.json. This is mentioned in the doc => https://ant.design/docs/react/use-with-next#using-app-router

Fo reference => https://github.com/ant-design/ant-design/issues/45567

infodusha commented 7 months ago

Actually, the flicker still valid when streaming html It seems you either have style duplication or streaming support I kinda solved this with that trick:

'use client';

import { useRef, useState } from 'react';
import { useServerInsertedHTML } from 'next/navigation';
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';

export function AntdRegistry({ children }: React.PropsWithChildren) {
  const [cache] = useState(() => createCache());

  const alreadyInserted = useRef(new Set<string>());

  useServerInsertedHTML(() => {
    if (cache.cache.size === 0) {
      return;
    }
    for (const key of alreadyInserted.current.keys()) {
      cache.cache.delete(key);
    }
    const html = extractStyle(cache, true);
    for (const key of cache.cache.keys()) {
      alreadyInserted.current.add(key);
    }
    cache.cache.clear();
    return <style dangerouslySetInnerHTML={{ __html: html }} className='antd' />;
  });

  return (
    <StyleProvider cache={cache} hashPriority='high'>
      {children}
    </StyleProvider>
  );
}

But i am not aware if relying on cache keys is fine in all the edge cases

infodusha commented 7 months ago

I also created a bug with reproduction in the antd repo, so let me link in here just in case: https://github.com/ant-design/ant-design/issues/45955

galihlprakoso commented 7 months ago
-- import { createCache, extractStyle } from '@ant-design/cssinjs';
++ import { createCache, extractStyle } from '@ant-design/cssinjs/lib';

This solved mine!

codingwaysarg commented 7 months ago

Same issue here, using:

"@ant-design/cssinjs": "^1.18.0-alpha.5",
"antd": "^5.11.4",
"next": "14.0.3",
"react": "^18",
"react-dom": "^18"

EDIT: I used "@ant-design/cssinjs": "1.17.5" and it worked.

jknap commented 7 months ago

Same issue here, using:

"@ant-design/cssinjs": "^1.18.0-alpha.5",
"antd": "^5.11.4",
"next": "14.0.3",
"react": "^18",
"react-dom": "^18"

EDIT: I used "@ant-design/cssinjs": "1.17.5" and it worked.

Yes you need to run npm ls @ant-design/cssinjs and make sure that your @ant-design/cssinjs version is the same as the one used by antd itself. This is explained in the Antd NextJS doc, although I missed it the first time. Might be worth fixing that as many of us are running into the issue.

Stuart88 commented 7 months ago

This is driving me nuts, I've tried all the solutions mentioned above and still the antd styles are not pre-rendering.

I inspect the content created by return <style id="antd" dangerouslySetInnerHTML={{ __html: extractStyle(cache, true) }} />; (as dictated in the docs) and I see that the result looks like this.

<style id="antd">.data-ant-cssinjs-cache-path{content:"";}</style>

It seems the extractStyle function is not doing very much.

I have no idea what else to try.

My cssinjs version numbers match.

image

vankop commented 5 months ago

@Stuart88 Did you find a solution?

Stuart88 commented 5 months ago

@Stuart88 Did you find a solution?

Nope, I chose to ignore it.

In my case, the app loads fast enough for the css loading flicker to not be too much of a problem.