Next.js: Safari renders twice while coming back from external page

Created on 10 Nov 2018  路  4Comments  路  Source: vercel/next.js

Bug report

Describe the bug

On Safari11, if one leave the nextjs app by going to an external url and hits the back button of the browser, getInitialProps of the last visited page is called twice, once on the server and once on the client side.

To Reproduce

1) Create an empty project directory. Create the following package.json file inside.

package.json:

{
  "name": "nextsafarireprod",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "next": "7.0.2",
    "react": "16.6.1",
    "react-dom": "16.6.1"
  }
}

2) Initiate npm install
3) Create a /pages directory inside the project directory
4) Create index.js and about.js files in the /pages directory with the following content, in the respective order:

//index.js

import Link from 'next/link';
export default class Index extends React.Component {
    static async getInitialProps({req}) {
        if (req) {
            return {txt: 'server'}
        }
        else {
            return {txt: 'client'}
        }
    }

    render() {
        return (
            <div>
                <p>Hello Next.JS!</p>
                <p>
                    <Link href="/about" passHref prefetch>
                        <a>Go to About</a>
                    </Link>
                </p>
                <p>{this.props.txt}</p>
            </div>
        )
    }
}
//about.js

export default class About extends React.Component {
    static async getInitialProps({req}){
        await new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve(true);
            },1500)
        });

        if(req){
            console.log('initialProps: server');
            return {txt: 'server'}
        }
        else{
            console.log('initialProps: client');
            return {txt: 'client'}
        }
    }

    render(){
        console.log(this.props.txt, new Date().toISOString());
        return (
            <div>
                <p>
                    <a href="http://www.google.com">Go to Google!</a>
                </p>
                <p>{this.props.txt}</p>
            </div>
        )
    }
}

5) Run npm run build; npm start for starting a local production server
6) Go to localhost:3000 and open your browser's console
7) Navigate to /about page by the link on the index page (this uses next's Link component)
8) Navigate to google by the link on the about page (this is old-school anchor tag)
9) Hit the back button of the browser, Safari will clear the console while moving back to the nextJS app.
10) Observe the new outputs on the console

Expected behavior

I would expect a server refresh only, as it happens successfully on Opera and Chrome.

Screenshots

Screenshot of the Safari Dev Console after coming back from the external page:

screen shot 2018-11-10 at 02 57 58

System information

  • OS: macOS High Sierra 10.13.6 - macbook pro 2017
  • Browser: Safari 11.1.2
  • Version of Next.js: 7.0.2

Additional context

Delete the .next folder, rebuild and restart the server and open a new private window from scratch every time you retry this, as both browser and the nextjs server tend to cache the pages

Addendum:

Additionally, Firefox on macOS does neither server nor client refresh in such a case. Normally (if user do not leave the app), going back inside the app always triggers server ssr refresh in any browsers that i have tested so far. but when leaving occurs, safari and firefox behaves strangely in two different ways :/

needs investigation

Most helpful comment

Any news about when Next.js will be back compatible with iPhone? The #6652 looks fix that, but it's waiting for merge. How can I help with that?

All 4 comments

I have the exact same problem, only Safari on Mac and IOS having the problem. Works fine in other browsers.

EDIT:
Just upgraded to 7.0.2, and the problem disappeared for me

EDIT again:
Nope problem still exists, was browser caching

Any news about when Next.js will be back compatible with iPhone? The #6652 looks fix that, but it's waiting for merge. How can I help with that?

"scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "isomorphic-unfetch": "^3.0.0",
    "next": "^8.0.3",
    "react": "^16.8.5",
    "react-dom": "^16.8.5",
    "styled-components": "^4.2.0"
  },
  "devDependencies": {
    "babel-plugin-inline-react-svg": "^1.0.1",
    "babel-plugin-styled-components": "^1.10.0"
  }

Safari: 12.1 (14607.1.40.1.4)
macOS: 10.14.4 (18E226)

The same issue occur when I tested in Safari. Chrome had only rendering(server side) once when navigating back from external URL.


Update: @8.0.5-canary.28 the issue has solved.

Beware, this bug is back in the latest version of Safari Version 13.0.1 (13608.2.11.1.10). Same with iOS 13.1. Is there anything that can be done in the nextjs lib, I have tried 9.0.6, 9.0.5, and 8.1.0 to no avail.

Chrome is working fine, but when you click the back button from an href (only) safari wants to load that as a client side call instead of a server call like chrome does.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

swrdfish picture swrdfish  路  3Comments

flybayer picture flybayer  路  3Comments

havefive picture havefive  路  3Comments

timneutkens picture timneutkens  路  3Comments

lixiaoyan picture lixiaoyan  路  3Comments