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

Flash of Unstyled Content in V2 #7516

Closed
1 task done
martinmckenna opened this issue Sep 22, 2023 · 27 comments
Closed
1 task done

Flash of Unstyled Content in V2 #7516

martinmckenna opened this issue Sep 22, 2023 · 27 comments
Labels
bug Something isn't working package:css-bundle

Comments

@martinmckenna
Copy link

martinmckenna commented Sep 22, 2023

What version of Remix are you using?

2.0.1

Are all your remix dependencies & dev-dependencies using the same version?

  • Yes

Steps to Reproduce

  1. create v2 remix app with streaming and route-based CSS that is requested on route change
  2. See flash of unstyled content between page loads

Here is an mp4 of my staging site that is running remix v1 (with no streaming). as you can see, there is no flash of unstyled content, even though the route CSS is being reloaded on each page route:

redacted

and here is a video of my production site (running remix v2 with streaming) and most of the time, the page margins and paddings and widths are jumping after the CSS was reloaded and applied:

redacted

FWIW, I also observed this only happens in chromium browsers

Regardless of the site, my methods for CSS have remained the same:

  1. On initial load, the component-level CSS, which sets things like colors, padding and margins on buttons, links, menus, tables, etc are fine
  2. Each route CSS file really only contains things like higher-level widths, margins, and paddings and this gets loaded on each route change
    • this is also why I'm only seeing a flash for the actual layout and not colors

Expected Behavior

No flash of unstyled content

Actual Behavior

flash of unstyled content

@martinmckenna
Copy link
Author

martinmckenna commented Sep 22, 2023

if the answer to this is "this is the tradeoff with using APIs like createReadableStreamFromReadable," that's fine I suppose, but it'd be nice to have some kind of official message on whether this is expected behavior or not and maybe some tips to avoid this.

actually just reverted back to renderToString in v2 and it still happens, so it seems unrelated to streaming. I also reverted back to hydrate instead of hydrateRoot and removed startTransition and none of that fixed the flash, so it must be something i don't have control over.

I feel like i'm just going to have to bundle ALL my CSS and not have any route-specific stuff

@Erij-Maherzia-BEN-BRAHIM

The flash of unstyled content is not related to V2, I had the same issue with V1 and I resolved the issue by wrapping my routes with a loading component when the page isn't hydrated.
Here is an example of a loading component 👇🏻

import { type ReactNode } from "react";
import { useHydrated } from "remix-utils";

export function Loading({ children }: { children: ReactNode }) {
  const isHydrated = useHydrated();

  if (isHydrated) {
    return (
        <div className="animate-appear">{children}</div>
    );
  }
  return (
<div>Loading...</div>
  );
}

@moishinetzer
Copy link

Wrapping all pages in a loading spinner is inherently anti-remix and should not be used as the default - or the solution.

To contrast where this is intended, take a look at the docs for streaming in remix.

Are there any updates on this issue?

@brophdawg11
Copy link
Contributor

Could you provide a reproduction repo for troubleshooting?

@brophdawg11 brophdawg11 added needs-response We need a response from the original author about this issue/PR package:css-bundle labels Sep 27, 2023
@martinmckenna
Copy link
Author

martinmckenna commented Sep 27, 2023

FWIW, i switched from styled-components to vanilla CSS when i upgraded to V2 as well, so other users are right - it might totally be a v1 thing as well, that i just never noticed because i had an extra render happening to inject the styled-components stylesheet

@brophdawg11 i can work on getting a repro case when i get some time away from work

@github-actions github-actions bot removed the needs-response We need a response from the original author about this issue/PR label Sep 27, 2023
@martinmckenna
Copy link
Author

@brophdawg11 most minimal example of just some content flex-flow: rowing after route client render. More details in the README:

https://github.com/martinmckenna/remix-bug

@ngbrown

This comment was marked as outdated.

@martinmckenna
Copy link
Author

@ngbrown yep totally understand this. but the issue is remix boasts about it's route-based styles, and if they provide an objectively worse experience, then it's not really a usable feature.

FWIW, i did end up combining my stylesheets into one that gets loaded on first visit, and it solved the problem, but either remix needs to figure this issue out or stop recommending people use route-loaded styles.

@azuisleet
Copy link

This same sort of issue exists for developers who want to split i18next strings into separate namespaces. You have to follow the same convention here of either combining all the assets/strings or preloading nearby assets in anticipation of navigation to another route.

Ideally there would be a mechanism for routes to specify assets necessary for the first render (after the initial page load) like style sheets and translation strings.

@brophdawg11
Copy link
Contributor

This is a bug in Remix. It got introduced when we switched the internals of Remix to use React Router's route.lazy functionality, where lazily loaded routes are losing the prefetch step for route-driven styles on subsequent navigations to those routes. I'll get a fix up for this shortly 👍

@brophdawg11 brophdawg11 self-assigned this Oct 2, 2023
@brophdawg11 brophdawg11 added bug Something isn't working and removed bug:unverified labels Oct 2, 2023
@brophdawg11 brophdawg11 added the awaiting release This issue has been fixed and will be released soon label Oct 5, 2023
@brophdawg11 brophdawg11 removed their assignment Oct 5, 2023
@brophdawg11
Copy link
Contributor

This is resolved by #7576 and will be included in the next release 👍

@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 2.1.0-pre.0 which involves this issue. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@sourcec0de
Copy link

sourcec0de commented Oct 12, 2023

Hello 👋

We're experiencing a similar issue to OP on 2.1.0-pre.0.
This appears to be caused by all stylesheet rendering twice.
As this group has pointed out JS is swapping the stylesheet, causing a flash of unstyled content.
This happens in production mode even with a statically built CSS file and postcss, tailwind options disabled.
It also doesn't matter if you link the stylesheet statically in the <head> tag or use const export links.

The screenshot is taken running in development.
CleanShot 2023-10-12 at 16 56 22

Here's a video that demonstrates the issue.
https://www.dropbox.com/scl/fi/06syjou7kxiyuqdso000a/flash-of-unstyled-content.mp4?rlkey=qogk2sfyre655ars6ry06hntv&dl=0

@brophdawg11
Copy link
Contributor

@sourcec0de I don't think you're reporting the same issue. Your video shows a FOUC on initial page load. OP's issue was a FOUC on client-side navigations to lazily loaded routes with CSS with caching disabled. Can you open a new issue with a reproduction so we can look into your initial load FOUC?

@martinmckenna
Copy link
Author

@sourcec0de i'm assuming this will go away if you revert back to hydrate instead of hydrateRoot. I had that issue and that's how i solved it.

but definitely worth a new remix issue either way

@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 2.1.0 which involves this issue. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@tb-b
Copy link

tb-b commented Oct 17, 2023

I'm still experiencing the same as @sourcec0de on 2.1.0

@brophdawg11
Copy link
Contributor

@tb-b Could you open a new issue with a reproduction?

@brophdawg11 brophdawg11 removed the awaiting release This issue has been fixed and will be released soon label Dec 14, 2023
@AmreeshTyagi
Copy link

This flash issue is still coming with remix 2.3.1 and react@18.2.0.

So, I switched to "react": "^18.3.0-canary-593ecee66-20231114", "react-dom": "^18.3.0-canary-593ecee66-20231114", and it is completely gone. Though I still see rehydration issue in console logs, but screen flash (cls-> cumulative-layout-shift) issue is gone.

It confirms that flash issue is related to React not with Remix.
I just followed this hydration issue thread. #4822 (comment)

@adaboese
Copy link

Thanks @AmreeshTyagi . I ended up deploying 18.3.0-canary-593ecee66-20231114 as well, and it fixed my issue as well.

Do you know what else changed in React v18.3?

Before:

Screenshot 2023-12-23 at 8 09 59 PM

After:

Screenshot 2023-12-23 at 8 09 51 PM

@sourcec0de
Copy link

sourcec0de commented Mar 12, 2024

Upgrading to react 18.3.0-canary-338dddc08-20240307 resolved our issue

@deadcoder0904
Copy link

I am also seeing a Flash for a millisecond without styles when I switched from plain Remix to Vite based setup.

I didn't see it before Vite switch. Not using any canary versions.

@Kallyan01
Copy link

i am using remix cloudflare setup , noticed this issue on first visit when page is not cached .

@Kallyan01
Copy link

Kallyan01 commented Mar 22, 2024

The issue is resoled , I found that FOUC was happening because of third-party extension (Grammarly) , removed it and now FOUC gone in initial load ,
But i have noticed another FOUC on the ErrorBoundary in root.tsx

export function ErrorBoundary() {
  const error = useRouteError();
  console.error(error);
  return (
    <html>
      <head>
        <title>Oh no!</title>
        <Meta />
        <Links />
      </head>
      <body>
        <Error/>
        <Scripts />
      </body>
    </html>
  );
}

@deadcoder0904
Copy link

@Kallyan01 i also have grammarly installed. i don't see anything in incognito window where all extensions are disabled.

i'm wondering if this happens only on localhost or production applications face the same FOUC issue.

@nilansaha
Copy link

I am also seeing a Flash for a millisecond without styles when I switched from plain Remix to Vite based setup.

I didn't see it before Vite switch. Not using any canary versions.

Did you manage to fix it?

@deadcoder0904
Copy link

@nilansaha Nope I think. It works well incognito. I think it was a development only error.

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

No branches or pull requests