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

What is the best way to load page will all data loaded SSR but load page before data when client? #1429

Closed
babakness opened this issue Aug 21, 2017 · 9 comments

Comments

@babakness
Copy link

babakness commented Aug 21, 2017

Hey guys,

I'm trying to wrap my mind around the best way to do this. So when a user arrives at a page that is server rendered, the data should load all at once. BUT, when the user arrives at a page after load, it should load the page then load the data, so it feels snappy. This is how I'm doing this right now, is the best way to do this in Nuxt?

import axios from 'axios'
const getTemp = async (bool) => {
    try {
      const res = await axios.get('http://samples.openweathermap.org/data/2.5/weather?zip=94040,us&appid=API_KEY')
      return res.data.main.temp
    } catch (e) {
      return 'error'
    }
}
export default {
  async asyncData ({ isStatic, isServer }) {
    return {
      temp: process.server ? await getTemp() : null
    }
  },

  async created(){
    if(!this.temp) {
      this.temp = await getTemp()
    }
  }
}

Basically, I'm using asynData go get the pre-loaded data feel for SSR, but skipping this for client loaded pages. ie process.server ? await getTemp() : null. Then I'm using created to see if the variable is already set (as is the case when SSR) and if not then trigger a data fetch.

Is this the best way to go about this? Is there a better way? Thank you for your feedback.

This question is available on Nuxt.js community (#c1271)
@atinux
Copy link
Member

atinux commented Aug 21, 2017

Hi @babakness

I don't understand what you're tying to achieve. When the page is server-rendered, when loading the page, asyncData won't be called on client-side.

@babakness
Copy link
Author

Hey @atinux, right but when it is client-rendered asyncData is called but the page doesn't load until the data is ready. In the case of client rendered (and only client rendered cases) I want the page first then let the data load. Otherwise there is a delay the user experience as data loads. So here is what I've done

export default {
  async asyncData ({ isStatic, isServer }) {
    return {
      temp: process.server ? await getTemp() : null
    }
  },

  async created(){
    if(!this.temp) {
      this.temp = await getTemp()
    }
  }
}

asyncData checks if it is being called on the server, if so, it will load the data. The created method is called after the component is mounted since the data is already there if(!this.temp){...} it will not load data. Now should the user arrive here for a client-render, asyncData return right away and the page isn't waiting for data first. Then once it loads created detects that this.temp isn't set so it fetches the data.

My question was if there was an easier way to achieve the same result

  1. Server render, wait for data then send the page
  2. Client render, load the page then load the data. (no waiting for data before loading the page.)

@atinux
Copy link
Member

atinux commented Aug 21, 2017

I see what you mean @babakness

Keep in mind that you cannot use async for created since Vue.js does not handle asynchronous hooks.

Also, you should use mounted instead since it's only called on client-side.

We decided to call asyncData and wait on client-side to avoid frustrations for developers to handle an in-between state and add some v-if to know if the data has been loaded.

Actually your solution is the only one at the moment.

We may consider after 1.0 having an option to call the middleware, asyncData & fetch after the navigation to the new page for client-side but it's not our priority sorry.

@atinux atinux closed this as completed Aug 21, 2017
@babakness
Copy link
Author

@atinux Got it, thanks! I appreciate the tip regarding mounted. Interesting, the code with async before created does work! I believe babel handles this, it essentially becomes this

...
 created: function() {
     if(!this.temp) {
      getTemp().then(function(response){
          this.temp = response
      })
    }
...

Not sure if this is what you meant regarding async and `created. Also, I believe the actual babel code is a bit more involved and uses generators to simulate this effect. For example

https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&targets=&browsers=&builtIns=false&debug=false&code_lz=MYewdgzgLgBAZiEMC8MDeAoGMCGECeYwMwATgKY5TkAmAFAJTpbYwVQCupYuA7jgEtYAIxylGLAL4ZJQA

Anyway, thanks.

@camilodelvasto
Copy link

@atinux I'm not sure I understand this:

... When the page is server-rendered, when loading the page, asyncData won't be called on client-side.

Have a look at this example: https://nuxtjs.org/examples/async-data/

I uploaded it here: https://dist-hyxzzudifb.now.sh/posts

So now my question:

  • Is it possible to have exactly that behavior (that no api call is made if the rendered version for that route exists) when accessing the /posts route from the home page link?

Thanks in advance for your help.

@jameshhood
Copy link

I'm running into a similar dilemma. I have a purchasing app where it has to pull a lot of user based data from a server. All examples say I should hook the data fetching in asyncData. I've done that between the middleware and the async data the loading indicator is going ballistic and very misleading. This causes a very bad user experience. There are tons of very helpful examples out there for fetching the data and explaining the best way to do so, but nothing out there explaining helpful ways to increase the user experience. If i click on a button and I want to see animations and some progress being made but if that progress bar is sporadic then i dont know if something is going on in the background or not. I'm still not very sure what the best way to handle this situation is because userdata is supposed to be fetched on the server, but yet it causes the progress bar to be useless

@rubenclaes
Copy link

@jameshhood @camilodelvasto How did you guys solve this?

@camilodelvasto
Copy link

@rubenclaes I couldn't find a solution... but I found a workaround. I wanted to load a child route with external content that was taking a long time to be generated, so it was too slow when I was coming from the home page. I ended up pre-fetching the data for that route, so when the user is coming from the home page, the data is already in the store and ready to use. The navigation is now snappier, but it takes a bit more for the home page to load.

@lock
Copy link

lock bot commented Nov 29, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 29, 2018
@danielroe danielroe added the 2.x label Jan 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants