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

UI flicker in simple-auth example #17082

Closed
thomasjm opened this issue Aug 26, 2019 · 12 comments
Closed

UI flicker in simple-auth example #17082

thomasjm opened this issue Aug 26, 2019 · 12 comments
Labels
stale? Issue that may be closed soon due to the original author not responding any more. type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@thomasjm
Copy link

Description

The simple-auth has an undesirable UI flicker when the app is built and used.

Based on whether the user is logged in or not, there is a piece of text that either reads "To get the full app experience, you’ll need to log in" or "Logged in as Jim (jim@example.org)! log out".

But when you load the page as a logged-in user, there's a brief flicker where the logged-out text is seen. (I tried to take a gif of this but it seems to happen a little too fast to easily capture--it's clearly visible to the eye though.)

I suspect the problem is the following: once a Gatsby site is built, it has already statically generated the pages. Since the app is in the "logged-out" state when the site is being generated, the logged-out text gets baked into the app. The logged-in text doesn't have a chance to render until the page is already loaded in the browser and the wrong text has already been seen.

I'm having this exact problem in a real app. One workaround I've tried is to make the element invisible during the logged-out state, so that it doesn't render at all until there's a React render in the browser. But this isn't very satisfactory, because then the rest of the page renders instantly and then the login status text appears a heartbeat later.

I'm really hoping there's a way to combine statically rendered pages with login/logout or similar state and have the page come up without a flicker. If all else fails I guess I could render two entire copies of my site, one logged-in and one logged-out...

Steps to reproduce

  1. git clone git@github.com:gatsbyjs/gatsby.git && cd gatsby/examples/simple-auth
  2. npm install
  3. npm run build
  4. python3 -m http.server 8080, open localhost:8080 in a browser, log in as the app suggests and try refreshing the page.

Note that the problem does not occur in a gatsby develop environment, but only once the site has been built.

Expected result

There should not be a UI flicker. It should load immediately with the correct text.

Actual result

It flickers.

Environment

  System:
    OS: Linux 5.0 Ubuntu 19.04 (Disco Dingo)
    CPU: x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
    Shell: 5.5.1 - /usr/bin/zsh
  Binaries:
    Node: 10.15.2 - /usr/bin/node
    Yarn: 1.12.3 - /usr/bin/yarn
    npm: 6.9.0 - ~/.yarn/bin/npm
  Browsers:
    Chrome: 72.0.3626.121
    Firefox: 68.0.2
  npmPackages:
    gatsby: ^2.0.0 => 2.13.83
    gatsby-plugin-react-helmet: ^3.0.0 => 3.1.5
@thomasjm
Copy link
Author

Managed to capture a higher framerate gif. Here's what it looks like when I refresh 3 times:

Peek 2019-08-27 16-18

Friendly ping @KyleAMathews , could you take a look at this?

@georgiee
Copy link
Contributor

That's expected behaviour.

Your browser receives a plain html file that is being hydrated on the client as described by you already. There is a roundtrip for the authentication or whatever your are doing on the client side that is different from the pre-generated file. That roundtrip costs time and is visible to you. Throttle your network and it will be even more visible. You can observe the exact same thing when you visit https://store.gatsbyjs.org/. Put something in the cart and reload. You will see the badge on the cart icon appearing after the page is loaded.

In Gatsby Develop mode it might be just quicker due to the hot page reloading environment you have running but that's not what you are dealing with in production.

Three options that pop my mind:

  • Maybe you can ask the designers for an alternative where it doesn't look that prominent (like the icon + badge)
  • Live with it — because users have a different image of the world than us developers. They are less offended by stuff like this.
  • Rethink your choice of technology. Frameworks like Next.js does real SSR (server-side rendering) while Gatsby does SSG (server-side generation). With a real server running process you can access a user's session and render the html accordingly before you deliver it on each request.

In the last bullet I mention SSR vs. SSG. I think SSR fits your expectation. It's the "classical" approach where you generate the output on the server-side per user request. Keep in mind that Gatsby does SSR too but only once during build time for all pages and of course without the individual user session at hand. That's why I like the term SSG. The lines between SSR/SSG and maybe caching are of course a little bit blurry.

@georgiee georgiee added the type: question or discussion Issue discussing or asking a question about Gatsby label Aug 29, 2019
@thomasjm
Copy link
Author

There is a roundtrip for the authentication or whatever your are doing on the client side that is different from the pre-generated file.

There's no network roundtrip in this example--it's just checking a cookie. That's why I was hopeful that there could be a Gatsby-based solution.

I think it's pretty common to have an app that's "almost 100% static." Like in my case, I just want a navbar at the top of the page to show either a login button or a "your profile" button based on the presence of a cookie (which could be checked either on the frontend or backend). The site is otherwise completely static.

It would be really nice if Gatsby could handle a situation like this without unpleasant visual artifacts. I recognize that this is difficult to do with pre-rendered pages, especially given Gatsby's commitment to being able to be served in a purely-static environment like an S3 bucket. But if a solution could be found I think it would hit a lot of use-cases that would otherwise push people toward Next.js.

Maybe the simple-auth example should be removed from the official Gatsby repository, since it comes with an unfixable bug and sort of offers false hope to people :P

For my part, I'm porting my app to Next.js. Which is a shame, since Gatsby has been great otherwise.

Feel free to close this issue if desired.

@KyleAMathews
Copy link
Contributor

We should just fix the example. The general pattern is to delay rendering things like that until the client js is loaded. It's far less noticable then. @thomasjm would you like to PR the change?

@KyleAMathews
Copy link
Contributor

In other words, check if window is defined before rendering something to avoid rendering during SSR

@thomasjm
Copy link
Author

That solution is much less noticeable, but when I tried that on my own app I found it was still too noticeable to use on something as prominent as the main navbar that appears on every page of my site.

I think I'm going to be putting my energy into the Next.js version now, sorry. (In addition to this issue there are a couple other places where more flexible SSR is attractive to me as well.)

@KyleAMathews
Copy link
Contributor

Have you tried gatsby-plugin-offline? This gets you around things as logged in & returning users load the site purely client side -- a lot faster than SSRing every time.

@thomasjm
Copy link
Author

Hmm...looks interesting. I'm not very familiar with service workers. It looks like going that route involves sacrificing IE11 support. It seems like a rather large change to make, and I suspect regular SSR fits my needs best. I'll have to read about service workers further, thanks for the recommendation!

@thomasjm
Copy link
Author

You know how Next.js allows you to augment a React component with a getInitialProps function, which is called during the SSR render? I wonder if Gatsby could do something similar, except that getInitialProps would be evaluated in the browser and the first React render would be delayed until it completed. I know this sort of defeats the purpose of pre-rendered pages and slows down the initial load, but it might be useful for situations like this.

@onestopjs
Copy link
Contributor

You know how Next.js allows you to augment a React component with a getInitialProps function, which is called during the SSR render? I wonder if Gatsby could do something similar, except that getInitialProps would be evaluated in the browser and the first React render would be delayed until it completed. I know this sort of defeats the purpose of pre-rendered pages and slows down the initial load, but it might be useful for situations like this.

That doesn't seem any different than "traditional" React patterns - load something on mount and set a loading flag. On load, remove the loading flag. While the loading flag is set, don't render the component. Or just straight up Suspense.

My point is, this is not something Gatsby should implement but should be left for the user to implement it the way they want it to work, let's not opinionate the core Gatsby.

@gatsbot
Copy link

gatsbot bot commented Sep 24, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Sep 24, 2019
@gatsbot
Copy link

gatsbot bot commented Oct 5, 2019

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks again for being part of the Gatsby community!

@gatsbot gatsbot bot closed this as completed Oct 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale? Issue that may be closed soon due to the original author not responding any more. type: question or discussion Issue discussing or asking a question about Gatsby
Projects
None yet
Development

No branches or pull requests

4 participants