How to handle apollo client errors crashing page render in Nuxt? - vue.js

I'm currently maintaining a production Nuxt.js Vue app that integrates GraphQL Apollo Client that's running into page render errors. For the sake of boosting my chances of getting a response, I built a bare-bones code example that showcases only the problem we are running into. Thanks everybody.
Source Code
Client, https://github.com/sgarcia-dev/error-apollo-client-nuxt
Server, https://github.com/sgarcia-dev/error-apollo-server
The Problem
The problem, is that every now and then, the GraphQL server we rely on (we have no control over it) goes down and returns a HTML error page, which crashes Apollo Client due to its attempt to parse the GraphQL spec JSON response. This yields the infamous Unexpected token < in JSON at position 0 error that's been reported over and over again.
The thing is, because we are using the #nuxt/apollo Nuxt module that integrates Apollo into the render pipeline, this makes Nuxt's page render crash. Giving us a generic server render error page that looks like this;
ERROR Network error: Unexpected token < in JSON at position 0 08:11:04
at new ApolloError (node_modules/apollo-client/bundle.umd.js:92:26)
at node_modules/apollo-client/bundle.umd.js:1588:34
at node_modules/apollo-client/bundle.umd.js:2008:15
at Set.forEach (<anonymous>)
at node_modules/apollo-client/bundle.umd.js:2006:26
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (node_modules/apollo-client/bundle.umd.js:2004:20)
at node_modules/apollo-client/bundle.umd.js:1483:29
at processTicksAndRejections (node:internal/process/task_queues:94:5)
How to reproduce the error
Clone the repositories from above, and start both of them following the readme.md commands. (for the server error, make sure to run npm run start-express since that's the one that crashes the client).
You'll notice the pages/index.js throws a server error page since the server returns an invalid HTML response.
What we tried
We tried following every error handling spec in the Vue Apollo and Nuxt apollo docs, but nothing seems to work. We tried:
Adding the Nuxt "#apollo/nuxt" module supported error handler syntax. It gets logged correctly, but the error doesn't stop propagating and crashes the page render. Even if we return false at the end. Which we thought that would, since that's what the source code for vue-apollo seems to do
Setting an apollo client errorPolicy of ignore and all, but the error still got through and crashed the page render
Adding individual query error() handlers and not relying on the global one. They stopped propagation to the global page, but it didn't stop the page render error from happening.
Using apollo-link-error's approach to ignoring errors by adding a link property to our nuxt apollo config and following those steps. The link configuration ran, and errors were indeed logged. But response in that example evaluates to undefined, stopping us from being able to do response.error. I assume its a Nuxt compatibility issue thing being SSR and all, and that this might be designed for React applications.
Summary
Even simple pages using nuxt/apollo module crash page render on an invalid GraphQL response, and we have no idea how to stop it from happening other than migrating our app from using nuxt/apollo and instead using apollo client directly which will be quite expensive.... any ideas?

Wouldn't it be possible to run your apollo queries through a computed property (which is displayed in the template). That way, you could check in the computed property for JSON errors and catch them there before making them available to the template render process.

Related

Has anyone experienced a network call where it works with cURL and Postman but not in localhost/simulator?

This is the weirdest experience I had so far. I made a hook that uses an endpoint that would work with react-query. Our company has our own SDK that wraps up all APIs and the format of our hooks would normally look the same.
Problem is, It does not work with my simulator/flipper. I even logged the response but comes undefined. I tried stripping all the stuff like react-query and instead used the SDK directly which is a wrapper for Axios.
Here are other observations:
The request is sent but never responds like giving an error or resolving with a value.
If you get the context menu and try to copy the cURL and use it in the terminal it works.
Copying the cURL to postman will work as well.
Tried deleting the build cache, and yarn cache, and cleaning up all the build folders and still gets the same result.

Invalid or unexpected token in Cypress

Even though I searched all over stackoverflow for the fix, I can't get past this error in Cypress:
"The following error comes from your application code, not from Cypress.
Invalid or unexpected token
When Cypress detects uncaught errors coming from your application, it will automatically fail the current test.
This behavior is configurable and you can choose to disable this by listening for the uncaught:exception event."
I've tried including the "main" workaround, whereby I put in the support/index.js code
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
The problem occurs in the console when cypress has to click on a selector for a menu on the page, which leads to a certain page.
This happens on a Public Release environment. On the base, staging environment, it works. Specifically, in cy.intercept() required and in cy.visit() instead of "/Public/" I changed to "/PublicRelease/". I've changed the links, intercepts and everything, but maybe I'm missing something.

Try it out functionality of tmdb api not working

When I tried to see data through try it out functionality then it is showing the following error
Error: Network Error
Check the developer tools console, it might have more information on the error.
If you are using an Adblocker, it is possible your Adblocker is blocking the request.
I also tried after disabling adblocker but it also does not work
console showing like this
Why this is happening and what is the solution for this?
Thanks in advance
Try the url in your browser with the API key. You can see the response.
Example :
https://api.themoviedb.org/3/movie/popular?api_key=your_api_key
Found out this is due to extension 'stoplight' in their site. Site Manager has said
"I believe Stoplight has temporarily blocked the "Try it out" feature for our account because too many people were using it as the source
for their apps, and not using api.themoviedb.org for some reason. No
timeline on getting it restored, but that's the problem. - Travis Bell"
follow this thread, In case it gets sorted in future.
https://www.themoviedb.org/talk/600184fc6aa8e0004077e364?page=1#6001bbacbe4b36003d514ac3
Apparently it depends on the way you try to access the data.
In my React application I was using Axios.Which ended up with ReferenceError: response is not defined. (got no response)
Afterwards I tried using the javascript fetch API. It worked good for me
So if you are trying to use it in an app you might want to use the fetch API. If you just encounter network error while using Try it out function on site - then you can copy the link and paste it directly, it should work fine.
Currently, I am using it in my dashboard and I have JWT authentication for the API that I'm using. I have implemented the interceptor to update HTTP HEADERS so I saw I'm passing a header name 'token' and checked there if any unnecessary headers were given or not with not accepting the TMDB API server. So I have sent a clean HTTP request and it's working fine.
All you have to just remove the unnecessary HTTP HEADERS

How does vue PWA use the precache? I still get "Page does not work offline"

I have a vue application that I updated to have PWA capability. It uses the firebase messaging service that has overridden the service worker with its own firebase-messaging-sw.js file.
The service worker is registered, active and working, I have added the pwa in the vue.config.js file so that it generates the manifest.json. When you build the production version of the app the following code gets added to the top of the service worker.
importScripts("precache-manifest.7b51ac9589a6dc8041a85d8f1792defa.js", "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
From what I see the percache works fine.
Should this be enough to get the site to work in offline mode?
Do I need to add some cache management myself?
What am I missing because I still get the "Page does not work offline" error message in Chrome's dev tools under the App manifest tab.
Looks like Google also picked up on the quick hack and the warning has returned.
So since of Chrome93 (AUG-2021) the quick hack, will not work anymore :
self.addEventListener('fetch', function(event) {})
Solution working "for now" (since we never know what requirements Google will add later on)
I've found a nice article which provides with a few solutions, the first one the author provides is Network-Falling-Back-To-Cache strategy:
your service worker will first try to retrieve the resource from your server. Then when it can’t do that — because for example, you’re offline — retrieve it from the cache (if it exists there).
self.addEventListener('fetch', function(event) {
event.respondWith(async function() {
try{
var res = await fetch(event.request);
var cache = await caches.open('cache');
cache.put(event.request.url, res.clone());
return res;
}
catch(error){
return caches.match(event.request);
}
}());
});
You can find all the information and alternative solutions in the article:
https://javascript.plainenglish.io/your-pwa-is-going-to-break-in-august-2021-34982f329f40
I hope this will help futur visitors.
Additional side note:
using the above code you might encounter the following error:
service-worker.js:40 Uncaught (in promise) TypeError: Failed to execute 'put' on 'Cache': Request scheme 'chrome-extension' is unsupported
This error is caused by chrome extentions like Augury or Vue dev-tools. Switching both off will cause the error to disappear.
You need to add this line in the serviceworker. It fools the browser into thinking that the page will work offline:
self.addEventListener('fetch', function(event) {}) // add this to fool it into thinking its offline ready

Auth0 access token to API works in postman but not when calling from Vue

I have 2 items set up in Auth0:
Application - Single Page Application
API - Custom API, machine to machine
I've followed the instruction in the link below to call the custom API:
https://auth0.com/docs/quickstart/spa/vuejs/02-calling-an-api
I've downloaded the sample with settings configured for both items mentioned above. The Vue app are able to log in correctly, and are able to call the external API by using the downloaded example codes (the external API, "backend", in the example code was written in Node JS).
However, when I change the backend to my Laravel/Lumen app which already set up for item no.2 (custom API), the Vue app received 401 unauthorized error. So, I copied the access token retrieved through Vue:
const accessToken = await this.$auth.getTokenSilently();
console.log(accessToken);
And try to call the Lumen backend with this access token - and it works perfectly fine!
Is there a setting somewhere that I might've missed to enable Vue & Lumen to work with Auth0?
p/s: The custom Lumen API was made following the instruction from:
https://auth0.com/blog/developing-restful-apis-with-lumen/
Ok it turns out I made a mistake in the axios part of the sample code. The sample is using get, while my API is using post. So I ended up sending the header in the wrong axios parameter. Hope this helps someone that encountered the same problem.