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

diffrent behaviors for browsers when page is restored from bfcache #44477

Open
1 task done
NamGungGeon opened this issue Jan 1, 2023 · 8 comments
Open
1 task done
Labels
examples Issue/PR related to examples

Comments

@NamGungGeon
Copy link

NamGungGeon commented Jan 1, 2023

Verify canary release

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

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:14:54 PDT 2022; root:xnu-8792.41.9~2/RELEASE_X86_64
Binaries:
  Node: 16.19.0
  npm: 8.19.3
  Yarn: 1.22.18
  pnpm: N/A
Relevant packages:
  next: 13.0.0
  eslint-config-next: 13.0.0
  react: 18.2.0
  react-dom: 18.2.0

Which example does this report relate to?

using-router

What browser are you using? (if relevant)

desktop safari 16.1(18614.2.9.1.12), desktop chrome 108.0.5359.124(x86_64)

How are you deploying your application? (if relevant)

No response

Describe the Bug

Before describe...

I test it on next.js 12, 13, canary.

All version has same issue.

You can simply reproduce issue here. (https://why-router-is-updated.vercel.app/)

Summary of used code

Original code(used) is here

```js
// page/index.js
function Home() {
  const router = useRouter();

  // alert if router is updated or init
  useEffect(() => {
    alert("router is updated(or init)");
    console.log("router is updated(or init)", router);
  }, [router]);

  // alert if e.persisted is true (page is restored from bfcache)
  useEffect(() => {
    const checkBfcache = (e) => {
      console.log("This page is restored from bfcache?", e.persisted);
      if (e.persisted) {
        alert("This page is served from bfcache");
      }
    };
    window.addEventListener("pageshow", checkBfcache);
  }, []);

  return (
    <>
      <Head>
        <title>Create Next App</title>
      </Head>
      <div>
        <h1>Currennt path: {router.asPath}</h1>
        <div>
          <h3>Inner links</h3>
          <ul>
            <li>
              <button onClick={() => router.replace("/?a=b")}>/?a=b</button>
            </li>
            <li>
              <button onClick={() => router.replace("/?a=b&c=d")}>
                /?a=b&c=d
              </button>
            </li>
            <li>
              <button onClick={() => router.replace("/")}>/</button>
            </li>
          </ul>
          <h3>Outer links</h3>
          <ul>
            <li>
              <Link as="a" href="https://www.google.com" passHref={true}>
                <button>https://www.google.com</button>
              </Link>
            </li>
          </ul>
        </div>
      </div>
    </>
  );
}

// prevent '/' be static page (running as dynamic page)
Home.getInitialProps = async ({ req, res }) => {
  res?.setHeader("Cache-Control", "private, no-cache, must-revalidate");
  return {};
};

export default Home;

How to invoke bug

  1. enter page. (/)
  2. click /?a=b button.
  3. click /?a=b&c=d button.
  4. click www.google.com(Outer link) button.
  5. click back button.
  6. bfcache is used. (page is restored without reload page)
  7. but router is updated, and useEffect(()=> {...}, [router]) is triggered.
    • page is restored from bfcache, thus router must be not updated. but router is updated, and effect is executed.
    • This bug is only generated from desktop/mobile safari, mobile chrome. (not generated from desktop chrome)

desktop chrome

  • when page is restored from bfcache, router is not updated. (not showed router update message alert)

desktop safari

- when page is restored from bfcache, router is updated. ( showed router update message alert)
  • same as mobile safari, mobile chrome.
  • but diffrent from desktop chrome...

What is problem?

Phase 7 is unexpected behavior.
(desktop/mobile safari and mobile chrome behavior is different from desktop chrome)

And also, in below situation, router is not updated on all browsers.

  1. enter page. (/)
  2. click www.google.com(Outer link) button.
  3. click back button.
  4. bfcache is used (page is restored without reload page)
  5. (important) router is not updated on all browser.
    • so useEffect(()=> {...}, [router]) is not triggered.

desktop chrome

  • when page is restored from bfcache, router is not updated. (not showed router update message alert)

desktop safari

- when page is restored from bfcache, router is not updated. (not showed router update message alert) - same as desktop chrome (also same as mobile chrome/safari)

Expected Behavior

When back button clicked from outer page(ex: google.com) and returned nextjs project pages, router must be updated or not updated on all browser. (do same behavior)

To Reproduce

Please see 'How to invoke bug' and 'What is problem' sections of Describe the Bug.

If you cannot understanding my descriptions, please add comment.

Thanks for your efforts!

@NamGungGeon NamGungGeon added the examples Issue/PR related to examples label Jan 1, 2023
@realamirhe
Copy link

realamirhe commented Jan 14, 2023

I have the same issue with the router.back method.
It doesn't have the problem on safari before 16.1 and tested within the discrete version till 13.3.

It causes the window.location.href to be updated when calling router.back but the page is not updated (render) new content.

It seems that the working solution StackOverflow suggest is to add an empty unload listener to the body, so it refreshes the page.

@NamGungGeon
Copy link
Author

NamGungGeon commented Jan 14, 2023

Setting 'unload' event listener means 'disable bfcache' also.

I need bfcache spec, so setting unload event listener is not solution.

@realamirhe
Copy link

@NamGungGeon isn't it wired that the nextjs showcases don't fall into bfcache issues even with the same version of browsers?

Did you find any solution?

@NamGungGeon
Copy link
Author

NamGungGeon commented Jan 23, 2023

@NamGungGeon isn't it wired that the nextjs showcases don't fall into bfcache issues even with the same version of browsers?

Did you find any solution?

Alternative solution I found is using deep-compare library(ex: https://www.npmjs.com/package/use-deep-compare) instead of useEffect about router.

Because router object is updated, but actually not changed inner values (router object inner values), so we can detect router is actually updated as comparing deeply router object.

@wherehows
Copy link
Contributor

wherehows commented Feb 20, 2023

Hello, i am the one who having trouble with bfcache.

few days ago, i got an answer from chatGPT that nextjs disable bfcache and in ssr evironment it is impossible to use bfcache because ssr render page and deliver browser.

Chat GPT says that to use bfcache browser can get all the asset for page like behavior in an CSR environment.

Since then, i see this issue today.

following for invoking bug step, I tried to reproduce bfcache. but i cant. I thought a lot about this situation and i tried to follow the step not window os but mac os and then i could reproduce bfcache.

I think how bfcache work might be the difference between OS. i comment for sharing.


안녕하세요. bfcache와 관련한 이슈 해결중에 있는 1인인데요.

얼마전에 chatGPT의 답변으로부터 ssr 환경에서는 bfcache 사용이 불가하고 nextjs는 bfcache를 disable 해놨다고 해서, 그런가보다 했는데 이 글을 마주치게 되었습니다.

들어가서 bfcache 재현 되도록 window환경에서 google 도메인에 이동했다가 뒤로가기를 했지만 bfcache로부터 복구가 안됐는데요.

원인이 무엇일까 생각하다가 mac으로 다시 확인해보니 100% 재현이 되네요..

아마 chatGPT가 정확한 정보를 제공한건 아닌 것 같고, bfcache의 동작이 OS에도 달라지는 것 같아서, 공유 차원에서 댓글 드립니다.

@kjk7034
Copy link

kjk7034 commented May 26, 2023

@NamGungGeon
I've tried something like this:

  const handlePageshow = useCallback(
    (event) => {
      if (event.persisted) {
        console.log('This page was restored from the bfcache.')
        reload()
      } else {
        console.log('This page was loaded normally.')
      }
    },
    [reload]
  )

  useEffect(() => {
    window.addEventListener('pageshow', handlePageshow)
    return () => {
      window.removeEventListener('pageshow', handlePageshow)
    }
  }, [handlePageshow])

@NamGungGeon
Copy link
Author

NamGungGeon commented May 28, 2023

@kjk7034

Your code is calling handlePageShow() when pageshow event is triggered.

That's irrelevant my issue.

My issue demonstrates that useEffect(()=> { ... }, [router]) does different behaviors depending on browser or OS.

@kjk7034
Copy link

kjk7034 commented May 30, 2023

I cloned your code and tested it, but my desktop chrome behaves differently.
(alert not working - bfcache is used ...)

My test environment : window10/Chrome 113.0.5672.127 + MacOS Big Sur (11.6.8)/Chrome 113.0.5672.126

As for the difference between Safari and Chrome, I think the following link will help you.
https://docs.google.com/document/d/1JtDCN9A_1UBlDuwkjn1HWxdhQ1H2un9K4kyPLgBqJUc/edit#

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
examples Issue/PR related to examples
Projects
None yet
Development

No branches or pull requests

4 participants