apollo icon indicating copy to clipboard operation
apollo copied to clipboard

Rendering errors during SSR

Open ulich opened this issue 5 years ago • 5 comments

I am using 3.0.0-beta.28.

If a graphql query is rejected with (e.g. network) errors, i want to render an error message in the component that initiated the query. This works fine on the client side with

  apollo: {
    messages: {
      query: messages,
      error(e) {
        this.error = e
      }
    }
  },
<div v-if="error">Oops. Something went wrong</div>

but when this component is rendered on the server it leads to a rejected serverPrefetch, which in turn stops the rendering of any component that comes after the current component.

What is the general idea on handling errors during server side rendering? When looking at the code, this seems to be implemented on purpose exactly how i experienced it.

My setup is a clean vue-cli 3 project:

vue create ...
vue add apollo
vue add @akryum/ssr

In version 3.0.0-beta.27 it works

ulich avatar Apr 23 '19 13:04 ulich

@Akryum Is there any resolve to this? I'm facing the very same issue on v3.0.3 and can't find any way around it when using server prefetch which we have to use. Any further info on this is very much appreciated!

jeissler avatar Feb 11 '20 22:02 jeissler

This issue is awfully quiet. Is this intentional? Is there some workaround? I've spent a few hours digging and haven't been able to come up with a good solution yet besides completely disabling prefetching, which isn't ideal... I attempted to write server middleware which would respond with a 200 response code, but as you might expect, the issue is whenever an error is present in the errors response and not just the HTTP code. Ideally I think the server should try to fill the data, and if it can't, then the client should try again.

robere2 avatar May 12 '20 05:05 robere2

I created a PR some time ago that will fix this issue but sadly there wasn't any response to it. https://github.com/vuejs/vue-apollo/pull/874

As a workaround a colleague of mine created this global mixin that will catch those errors and will log it:

export default {
  install(Vue) {
    Vue.mixin({
      beforeCreate() {
        // Prepare properties
        const { apollo } = this.$options

        if (!apollo) {
          return
        }

        // go through all queries
        Object.keys(apollo)
          .filter(key => key.charAt(0) !== '$')
          .forEach(key => {
            const options = apollo[key]
            const oldFn = options.update

            // check if update hook exists and has not already been wrapped
            if (options.update && !options.update.wrapped) {
              options.update = function safeApolloUpdate(...args) {
                try {
                  // call original function
                  return oldFn.call(this, ...args)
                } catch (e) {
                  logger.log('error', 'APOLLO_UPDATE_ERROR', {
                    message: e.message,
                    error: e,
                    data: {
                      component: this.$options ? this.$options.name : 'unknown',
                      apolloKey: key,
                      apolloResponse: { ...args },
                    },
                  })
                }
                return undefined
              }
              options.update.wrapped = true
            }
          })
      },
    })
  },
}

MrWook avatar May 13 '20 13:05 MrWook

I am using 3.0.0-beta.28.

If a graphql query is rejected with (e.g. network) errors, i want to render an error message in the component that initiated the query. This works fine on the client side with

  apollo: {
    messages: {
      query: messages,
      error(e) {
        this.error = e
      }
    }
  },
<div v-if="error">Oops. Something went wrong</div>

but when this component is rendered on the server it leads to a rejected serverPrefetch, which in turn stops the rendering of any component that comes after the current component.

What is the general idea on handling errors during server side rendering? When looking at the code, this seems to be implemented on purpose exactly how i experienced it.

My setup is a clean vue-cli 3 project:

vue create ...
vue add apollo
vue add @akryum/ssr

In version 3.0.0-beta.27 it works

Did you ever find a way to handle SSR errors with vue-apollo?

thevalleydev avatar Aug 15 '22 14:08 thevalleydev