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

[v2] [cache-dir] Fix navigation after reload #7812

Merged
merged 31 commits into from
Sep 13, 2018
Merged

[v2] [cache-dir] Fix navigation after reload #7812

merged 31 commits into from
Sep 13, 2018

Conversation

vtenfys
Copy link
Contributor

@vtenfys vtenfys commented Sep 2, 2018

We added popstate listeners to app.js and production-app.js which load the resources / render the page when back/forward is pressed.

onPreRouteUpdate and onRouteUpdate aren't currently being called when navigating with back/forward so this will need to be fixed later in order for plugins to work properly.

Note: wait until #7936 is merged to master before merging this PR, so we can properly test CI beforehand. Just merged master oops I got mixed up with a different one of DSchau's PRs which was merged

Fixes #7261

@pieh
Copy link
Contributor

pieh commented Sep 2, 2018

Some context on commented out on(Pre)RouteUpdate calls: we currently don't call onRouteUpdate when using history. I asked to comment them out, because with that they will run only in very specific scenario - hitting "back" after reloading window. This should be fixed in separately.

@KyleAMathews
Copy link
Contributor

With @pieh's PR improving our Cypress setup landing, it'd be nice for this PR to write a test for the reload and back button behavior which fails without the changes made here but then which the changes here do fix .

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 4, 2018

@KyleAMathews I've just added the new test - waitForRouteChange() doesn't seem to work with the 404 development page (it resolves after the URL changes but before the 404 appears) so I've gone for the approach of detecting whether the image wrapper element exists, since Cypress will auto-wait for this. I've tested before and after the changes to check it fails and passes correctly.

@pieh
Copy link
Contributor

pieh commented Sep 4, 2018

@davidbailey00 waitForRouteChange problem is related to problems with navigating through history and firing onRouteUpdate - it simply doesn't detect that route has changed in that case and only remember when DOM was updated after reload (before hitting back). Also this currently fail on travis - travis seems much slower, so that's why we added waitForRouteChange in the first place, because cypress timeouts were not reliable

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 4, 2018

@pieh With the Travis tests, currently we're not using gatsby-dev to copy the latest changes so it's expected to fail at the current stage (because it's using the latest published version). I'm pretty sure that it should pass once the update has been published, regardless of the speed of Travis, because Cypress will automatically wait until the div[to='/${post1.id}/'] element exists - the problem with earlier tests is that some elements did exist but Cypress clicked them before event handlers were setup, but there's no such problem here because it's just checking for the existence.

@pieh
Copy link
Contributor

pieh commented Sep 4, 2018

It will wait ~4s, which sometimes proved to be not enough on Travis - when you test this locally with cypress open - try throthling cpu (6x slowodown) and run test multiple times - it proved to quite ok mimic travis slowness. But defenitelly good point about gatsby-dev (which I sometimes forget :/)

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 4, 2018

@pieh In that case perhaps we can override Cypress's default timeout with something like 10 seconds - but I think it's unlikely Travis will be that slow in most cases, given that only two of the tests took longer than 1 second:

image

@KyleAMathews
Copy link
Contributor

The plan is to build code & run gatsby-dev for tests but yeah, that makes it more difficult now.

@davidbailey00 could you add tests to here as well? https://github.com/gatsbyjs/gatsby/tree/master/integration-tests/production-runtime

Gatsbygram is running the develop server.

@pieh
Copy link
Contributor

pieh commented Sep 5, 2018

Hey, when I was diving deep into PageRenderer.js for onRouteUpdate fixes for history I noticed we have code there to handle exactly this

loader.getResourcesForPathnameSync(pathName, pageResources => {
but this isn't correct and we didn't catch this before - this line should not be sync and use then:

-loader.getResourcesForPathnameSync(pathName, pageResources => { 
+loader.getResourcesForPathname(pathName).then(pageResources => {

I think changing this and reverting your changes from production-app.js and app.js should be correct way to fix this. And we still definitely want cypress test you added (which I would later modify a little to use onRouteUpdate when I fix that)

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 5, 2018

@pieh Nice find, I'll try changing this later tomorrow (just sorting out college stuff now).

@pieh
Copy link
Contributor

pieh commented Sep 5, 2018

Change I commented above fixed this for production, but development has a little different setup and we are getting stuck in JsonStore component before we even get to PageRenderer so I kept development change for now - ultimately I think we could move ad-hoc resources loading from PageRenderer somewhere higher in component tree - I'll experiment now for a bit, but won't spend too much time on it

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 6, 2018

@pieh Sounds good, thanks for making the changes! I've got my initial college homework out the way now so I'll try adding the tests requested by Kyle later on.

@KyleAMathews
Copy link
Contributor

Just thinking. We should publish our Cypress plugin to npm as people will want to use it when testing their gatsby sites as well. Plus it could lead to more useful Cypress plugins being added.

@pieh
Copy link
Contributor

pieh commented Sep 7, 2018

Just thinking. We should publish our Cypress plugin to npm as people will want to use it when testing their gatsby sites as well. Plus it could lead to more useful Cypress plugins being added.

I agree, I just didn't want to focus on finding proper way of packaging cypress extension + that API is very fresh and I'm not sure if it will stick and if we won't have to change it - I guess it would work if we release it as 0.x version when nothing is guaranteed ;)

@pieh
Copy link
Contributor

pieh commented Sep 7, 2018

Feeling pretty good about.

Here is some manual testing I did to ensure on(pre)RouteUpdate and resolving and resetting rout change promise is done in correct order and at correct times:

  • I disabled prefetching resources by doing early returns in hovering and enqueue functions here (
    hovering: rawPath => {
    const path = stripPrefix(rawPath, __PATH_PREFIX__)
    queue.getResourcesForPathname(path)
    },
    enqueue: rawPath => {
    const path = stripPrefix(rawPath, __PATH_PREFIX__)
    ) and verified by checking network tab (and additionally checking web socket frames in development for data)
  • my testing site was basicly gatsby-starter-blog with additional gatsby-browser.js that console.log on(Pre)RouteUpdate that checks actual DOM element with document.getElementById (titleElementInDom)
  • my testing methology was just loading index page in browser and then issuing following commands in same order for production and development:
    • window.___navigate('/hi-folks/') (go to page that exists)
    • window.___navigate('/this-will-be-404') (go to page that doesn't exist)
    • window.location.reload() (reload to start actually testing main thing that this PR should do :D)
    • window.history.back() (go back from 404 page to existing page)
    • window.location.reload()
    • window.history.forward() (go forward from existing page to 404)

Production:

Console output: screenshot (colorful yay)

screen shot 2018-09-07 at 03 53 42

Console output: text
Navigated to http://localhost:9000/
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resetRouteChangePromise
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "IndexPage", pathname: "/"}
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onRouteUpdate {titleElementInDOM: "IndexPage", pathname: "/"}
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resolveRouteChangePromise
window.___navigate('/hi-folks/')
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resetRouteChangePromise
undefined
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "IndexPage", pathname: "/hi-folks/"}
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resolveRouteChangePromise
window.___navigate('/this-will-be-404')
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resetRouteChangePromise
VM284 app-e36d6dfe3bf7e083bcc8.js:1 A page wasn't found for "/this-will-be-404"
undefined
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/404.html"}
VM284 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
VM284 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resolveRouteChangePromise
window.location.reload()
undefined
Navigated to http://localhost:9000/this-will-be-404
VM393 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resetRouteChangePromise
VM393 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
VM393 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
VM393 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resolveRouteChangePromise
window.history.back()
undefined
VM393 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resetRouteChangePromise
VM393 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/hi-folks/"}
VM393 app-e36d6dfe3bf7e083bcc8.js:6 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
VM393 app-e36d6dfe3bf7e083bcc8.js:1 [wait-for-route-change] resolveRouteChangePromise
window.location.reload()
undefined
Navigated to http://localhost:9000/hi-folks/
wait-for-route-change.js:3 [wait-for-route-change] resetRouteChangePromise
gatsby-browser.js:11 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
gatsby-browser.js:3 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
wait-for-route-change.js:12 [wait-for-route-change] resolveRouteChangePromise
window.history.forward()
undefined
wait-for-route-change.js:3 [wait-for-route-change] resetRouteChangePromise
gatsby-browser.js:11 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/404.html"}
gatsby-browser.js:3 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
wait-for-route-change.js:12 [wait-for-route-change] resolveRouteChangePromise

Development:

Console output: screenshot (colorful yay)

screen shot 2018-09-07 at 03 53 26

Console output: text
Navigated to http://localhost:8000/
VM2352 wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
VM2193 __webpack_hmr&reload=true&overlay=false:92 [HMR] connected
VM2308 gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: null, pathname: "/"}
VM2308 gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "IndexPage", pathname: "/"}
VM2352 wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.___navigate('/hi-folks/')
VM2352 wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
undefined
VM2308 gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "IndexPage", pathname: "/hi-folks/"}
VM2308 gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
VM2352 wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.___navigate('/this-will-be-404')
VM2352 wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
VM2309 loader.js:340 A page wasn't found for "/this-will-be-404"
undefined
VM2308 gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/404.html"}
VM2308 gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
VM2352 wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.location.reload()
undefined
Navigated to http://localhost:8000/this-will-be-404
VM2787 wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
VM2744 loader.js:340 A page wasn't found for "/this-will-be-404"
VM2628 __webpack_hmr&reload=true&overlay=false:92 [HMR] connected
VM2743 gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: null, pathname: "/404.html"}
VM2743 gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
VM2787 wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.history.back()
undefined
VM2787 wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
VM2743 gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/hi-folks/"}
VM2743 gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
VM2787 wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.location.reload()
undefined
Navigated to http://localhost:8000/hi-folks/
Users/misiek/dev/my-blog/.cache/wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
Users/misiek/dev/my-blog/node_modules/webpack-hot-middleware/client.js?path=http:/localhost:8000/__webpack_hmr&reload=true&overlay=false:92 [HMR] connected
Users/misiek/dev/my-blog/gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: null, pathname: "/hi-folks/"}
Users/misiek/dev/my-blog/gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/hi-folks/"}
Users/misiek/dev/my-blog/.cache/wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise
window.history.forward()
undefined
Users/misiek/dev/my-blog/.cache/wait-for-route-change.js:18 [wait-for-route-change] resetRouteChangePromise
Users/misiek/dev/my-blog/gatsby-browser.js:13 [gatsby-browser] onPreRouteUpdate {titleElementInDOM: "Post: New Beginnings", pathname: "/404.html"}
Users/misiek/dev/my-blog/gatsby-browser.js:4 [gatsby-browser] onRouteUpdate {titleElementInDOM: "NOT FOUND", pathname: "/404.html"}
Users/misiek/dev/my-blog/.cache/wait-for-route-change.js:31 [wait-for-route-change] resolveRouteChangePromise

Difference between dev and prod is that DOM element exists in production for onPreRouteUpdate after initial load and reloads (because of static html :) )

@pieh
Copy link
Contributor

pieh commented Sep 7, 2018

note to self: consider moving ScrollContext down in component tree as scroll position can reset now before new page have resources (f.e. after reloading page and going back)

}

static getDerivedStateFromProps({ pageResources, location }, prevState) {
if (prevState.location.pathname !== location.pathname) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to make shallow compare - location changes doesnt mean pathname changes

// Check if location has changed on a page using internal routing
// via matchPath configuration.
if (
this.props.location.key !== nextProps.location.key &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify key is there in @reach/router


return null
} else if (
process.env.NODE_ENV !== `production` &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify if this ever happen

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 9, 2018

The Cypress production test I added is failing 80% of the time with Electron 59, but working perfectly every time on the latest Chrome (which we can't use with CI). I spent a while this morning trying to figure out the problem but couldn't find it, and then had to do some other things - I'll have another look now.

@vtenfys
Copy link
Contributor Author

vtenfys commented Sep 9, 2018

It works! Travis still fails at the moment because we don't use gatsby-dev before testing, but #7936 will fix this (we should merge master to this PR, once #7936 is merged to master, to check it works).

@KyleAMathews
Copy link
Contributor

Great work @davidbailey00! Totally fine merging this w/ manual local testing until #7936 is working. I assume @pieh will get this in before I'm awake in the morning but if not, I'll test and merge.

@pieh
Copy link
Contributor

pieh commented Sep 10, 2018

We had conversation with @davidbailey00 and there is one more issue that need fixing here - in production sync loader.getPage things can fail to get page if we call it before we fetch pages metadata - which is what I think was causing problems on cypress/electron (and not really some bug there). So i currently work on that

@pieh
Copy link
Contributor

pieh commented Sep 10, 2018

still TO-DO - move scroll context component to PageRenderer

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

Successfully merging this pull request may close these issues.

[v2] Refreshing a page then hitting back (browser back button) leads to 404
3 participants