Nuxt.js: Caching API calls on server

Created on 17 Sep 2017  路  8Comments  路  Source: nuxt/nuxt.js

I'm guessing this is not something that Nuxt is ready to handle, but it can't hurt to ask. I'm using the OpenExchangeRates API to get exchange rates and change prices according to a country set in the Vuex store. This works fine, but the API only allows 1000 calls/month. Refreshing once an hour is fine with me, but is there any way to manage this using Nuxt? Is it possible to save the JSON response locally, and fetch that instead if it's not an hour old yet? It's trivial to implement in for example PHP, but not sure if it's possible in this case. Thanks!

This question is available on Nuxt.js community (#c1498)
documentation help-wanted question stale

Most helpful comment

@robyedlin you are right, I am actually myself often get confused with this.

@Atinux while going through issues I came across a number of them asking pretty much the same question. It's not clear at all hot to make sure data is cached on server side or the opposite. So I want to add the following scenarios to documentation. But need to clarify myself how to:

1) cache part of state on server (multiple requests will get shared content e.g. shared product list)
2) not cache part of state on server ( not share data with other requests e.g. user details)
a) allow for some data to be prepared on server ( e.g. user data rendered in SSR content)
b) data only to be retrieved on client (e.g. no user data in SSR content, client always requests it via api)
3) mix 1) & 2) for parts of data i.e. some part of state use 1) and other part 2).

Also you might have some content which is not part of the state, but good to cache on server (like caching server side axios calls), or use external cache service.

Once clarified I will try to produce a demo of this and update documentation, as it is very grey area to everyone. This is extremely important for anything serious involving SSR, as caching is were often up to 90% performance optimizations are lost/gained.

Anyone with suggestions, tips, best practices and etc please add here so that we can get the clear documentation out.

All 8 comments

Hi, @danielpost!

This how I handle API calls cache:
/plugins/cachedApi.js

import axios from './axios'
let data // simple data cache

const cachedApi = {
  getData () {
    return new Promise(function (resolve, reject) {
      if (data) { // get data from cache if exists
        resolve(data)
      } else { // else get data from API
        axios
          .request({
            url: '/api/get-data'
          })
          .then(response => {
            data = response.data // set data, so new getData() will take data from cache
            resolve(data)
          })
          .catch(reject)
      }
    })
  }
}

nuxt.config.js

plugins: ['~plugins/cachedApi ']

store/index.js

function nuxtServerInit ({commit}) {
  return new Promise(function (resolve) {
    cache.getData()
      .then(data=> {
        commit(types.DATA_LOADED, data)
        resolve()
      })
      .catch(error => {
        commit(types.SERVER_FAILED, error)
        resolve()
      })
  })
}

@KonstantinVlasov Sorry for the slow reply! This looks nice. Does it work with multiple people (ie if 20 people visit the page, it only fetches it for the first person and uses the cache for everyone else)?

@danielpost exactly 馃槃

Seems like a critical piece of this is left out, please correct me if I'm wrong.

The cache is only shared if your state is assigned as an object, not a function returning an object.

// shared client state, depending on how state is loaded in
const state = {
   data: 'your data'
}

// private client state
const state = () => ({
   data: 'your data'
})

@robyedlin you are right, I am actually myself often get confused with this.

@Atinux while going through issues I came across a number of them asking pretty much the same question. It's not clear at all hot to make sure data is cached on server side or the opposite. So I want to add the following scenarios to documentation. But need to clarify myself how to:

1) cache part of state on server (multiple requests will get shared content e.g. shared product list)
2) not cache part of state on server ( not share data with other requests e.g. user details)
a) allow for some data to be prepared on server ( e.g. user data rendered in SSR content)
b) data only to be retrieved on client (e.g. no user data in SSR content, client always requests it via api)
3) mix 1) & 2) for parts of data i.e. some part of state use 1) and other part 2).

Also you might have some content which is not part of the state, but good to cache on server (like caching server side axios calls), or use external cache service.

Once clarified I will try to produce a demo of this and update documentation, as it is very grey area to everyone. This is extremely important for anything serious involving SSR, as caching is were often up to 90% performance optimizations are lost/gained.

Anyone with suggestions, tips, best practices and etc please add here so that we can get the clear documentation out.

Generally I've found that global/shared state depends on any direct assignment in the store module.

Here's another case to look out for, independent of how you wrap the state:

This will globally store a privateToken for all clients:

const privateToken = generateTokenFunction()

const state = () => ({
  token: privateToken // uh oh, this is exposed everywhere
})

This will privately store the token for individual clients:

function privateToken () { 
  return generateTokenFunction()
}

const state = () => ({
  token: privateToken() // this is safe
})

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  路  3Comments

o-alexandrov picture o-alexandrov  路  3Comments

danieloprado picture danieloprado  路  3Comments

vadimsg picture vadimsg  路  3Comments

shyamchandranmec picture shyamchandranmec  路  3Comments