facebook / docusaurus

Easy to maintain open source documentation websites.
https://docusaurus.io
MIT License
55.97k stars 8.4k forks source link

Some CSS is not loaded when direct-linked to a built page #5475

Closed taylorreece closed 3 years ago

taylorreece commented 3 years ago

🐛 Bug Report

Prerequisites

Description

Hey Docusaurus team, I'm running into an odd issue starting in 2.0.0-beta.5 (still present on 2.0.0-beta.6) where some CSS that I generate in JSX components is not rendered properly when you link directly to a built docs page, but it does show up fine when running in docusaurus start or if you click out of the page with messed up CSS, and then back into it.

Here's an illustration: if you open this page directly you'll see some cards with no CSS applied to them https://613103da4ac20ffdfd0d68c8--happy-curie-b91cab.netlify.app/docs/changelog , but if you click into another docs page and then back to the "Illustrate Issue" page on the sidebar, the CSS renders fine.

Have you read the [Contributing Guidelines on issues]

Yes

Steps to reproduce

  1. Initialize a new docusaurus site
  2. yarn add @material-ui/core
  3. Add a few components that utilize makeStyles() and a couple of pages that use those components - https://github.com/taylorreece/docusaurus-css-issue/commit/e258b2f8745bf909dcd6ab098ffdfdca0e0ee3d8 illustrates a diff between a cleanly initialized Docusaurus site using 2.0.0-beta.6, and one with a couple components and docs pages
  4. Run yarn build and yarn serve; note that some pages with JSX components render fine, but if you refresh the page, or link to the built page directly, the CSS doesn't render right.

Expected behavior

Correctly rendered CSS on page load when linked directly to a docs page.

Actual behavior

If you link directly to https://613103da4ac20ffdfd0d68c8--happy-curie-b91cab.netlify.app/docs/changelog you don't get properly rendered CSS. image If you open another docs page and then click to the changelog page from the sidebar, CSS renders properly. image

Note: if I bump Docusaurus back down to 2.0.0-beta.4, the problem goes away. It seems like it was introduced between 2.0.0-beta.4 and 2.0.0-beta.5.

Your environment

Reproducible demo

Use https://new.docusaurus.io to create a CodeSandbox reproducible demo of the bug.

Unfortuantely this bug only appears if you build your project, and doesn't occur in the sandbox.

Example repo to illustrate the issue is at https://github.com/taylorreece/docusaurus-css-issue, though, and is split into two commits: the first commit is a clean initialization of a Docusaurus 2.0.0-beta.6 site using npx @docusaurus/init@latest init docusaurus-css-issue classic, and the second commit highlights the issue I'm seeing.

Thanks for your insight!

slorber commented 3 years ago

We don't support CSS-in-JS properly yet, as Docusaurus does have not lifecycle hooks to inline critical CSS-in-JS in the statically generated HTML files: https://github.com/facebook/docusaurus/issues/3236

MaterialUI is using JSS, a CSS-in-JS framework.

In any case, I strongly recommend not using it until we have better support, because it would only lead to flash of unstyled content before hydration, and the framework may not handle the React hydration well due to the lack of SSR integration that they probably recommend.

I find it very suspicious that it worked better on older Docusaurus versions, can you deploy one on beta.4 with the exact same Mui version and double-check? We didn't change anything related, and I suspect you just not noticed that it didn't work before, or you updated Mui at the same time?

In any case, I can't do much about it. We can clearly see that JSS classes are correctly rendered in the markup, but after hydration, the JSS classes are not inserted in the stylesheet. If you want to rely on JSS with Docusaurus (not recommended), then it's your responsibility to ensure JSS is correctly integrated with Docusaurus. In the future, someone will likely create a docusaurus jss plugin for that.

taylorreece commented 3 years ago

Hey @slorber - thanks for your feedback! I'll look into not using CSS-in-JS.

It does seem to work fine in beta.4. I first noticed the issue yesterday after a beta.5 update, and it seems to also have issues in beta.6. Here's a commit that reverts my POC repo back to beta.4 - https://github.com/taylorreece/docusaurus-css-issue/commit/8a4f61a56a441a0093451aa4ba98e105bede0b88 - and the corresponding Netlify deploy - https://happy-curie-b91cab.netlify.app/docs/changelog/ . The page has a flash of unstyled content, but then pulls in the correct CSS with beta.4.

What's weird to me is that the CSS doesn't just not load. With beta.5 and beyond, the wrong CSS class is applied. After direct-linking to https://613103da4ac20ffdfd0d68c8--happy-curie-b91cab.netlify.app/docs/changelog/ the gray part of my cards have generated class jss13: Screen Shot 2021-09-03 at 8 38 38 AM If I move to a different page and back they have the correct class jss16: Screen Shot 2021-09-03 at 8 39 04 AM Very odd.

Anyways, I'll keep an eye on #3236. Should I close this one as a duplicate of that?

slorber commented 3 years ago

We recently did a change that may produce this behavior: https://github.com/facebook/docusaurus/pull/5349

Basically, Docusaurus used to render uselessly twice on the client, leading to more resource usage on React hydration. I suspect on the 2nd render, JSS was able to "fix" the lack of SSR support in Docusaurus but is not able anymore since we optimized re-renders, so the fix only applies once you navigate.

Yes, I think we can't do anything here apart adding good CSS-in-JS support in Docusaurus, so let's track the other issue.

A possible workaround if you want to keep using Mui with bad integration/FOUC is to trigger this duplicate re-render yourself (as it was before).

Here's an example, no guarantee it works though:

export const ChangeLogEntry = ({ children, date }) => {
+  const isBrowser = useIsBrowser();
  const classes = useStyles();
  const formattedDate = dateFormat(
    new Date(date),
    "mmmm dd, yyyy",
    true // Account for timezones
  ).toUpperCase();

  return (
    <>
+      <Card key={isBrowser} className={classes.root}>
        <div className={classes.titleBar}>
          <span>{formattedDate}</span>
        </div>
        <CardContent className={classes.cardContent}>{children}</CardContent>
      </Card>
    </>
  );
};

You can also try wrapping Mui components with <BrowserOnly> and creating styles "lazily" in a useMemo hook?