Search code examples
server-side-renderingquasar-frameworkhydration

Why hydration errors happens only in production after few hours of deploying quasar application


I'm running into a weird situation here that debugging is becoming extremely hard to debug.

I have made a post here https://forum.cleavr.io/t/cloudflare-caching-in-a-quasar-app/844 thinking that the problem was about caching.

We are having hydration errors in our webapp codotto.com ONLY after a few hours (or minutes depending on website traffic). As soon as I redeploy the app, everything works well. No hydration errors anymore.

We had the idea that it was caching but we have disabled caching completely in our Cloudflare dashboard:

enter image description here enter image description here

Then we can verify that the cache is not being used:

enter image description here

Note the CF-Cache-Status set to DYNAMIC (refer to here to see that when you have DYNAMIC set in CF-Cache-Status header it means that cache is not being used).

Locally the app works great and we are not able to reproduce the issue locally and in staging as well. This only happens in production. Here we have configurations for pm2 settings:

production

// DO NOT MODIFY THIS FILE. THIS FILE IS RECREATED WITH EVERY DEPLOYMENT.
module.exports = {
  name: "codotto.com",
  script: "index.js",
  args: "",
  log_type: "json",
  cwd: "xxxx/codotto.com/artifact",
  // Note: We detected that this web app is running on a server with multiple CPUs and hence we are
  // setting *instances* to "max" and *exec_mode* to "cluster_mode" for better performance.
  instances : 1, // change the value to "1" if your server has only 1 CPU
  // exec_mode : "cluster_mode", // remove this line if your server has only 1 CPU
  env: {
    "PORT": 7145,
    "CI": 1,
    "NUXT_TELEMETRY_DISABLED": 1
  }
}

staging

// DO NOT MODIFY THIS FILE. THIS FILE IS RECREATED WITH EVERY DEPLOYMENT.
module.exports = {
  name: "staging.codotto.com",
  script: "index.js",
  args: "",
  log_type: "json",
  cwd: "xxxxx/staging.codotto.com/artifact",
  // Note: We detected that this web app is running on a server with multiple CPUs and hence we are
  // setting *instances* to "max" and *exec_mode* to "cluster_mode" for better performance.
  instances : 1, // change the value to "1" if your server has only 1 CPU
  // exec_mode : "cluster_mode", // remove this line if your server has only 1 CPU
  env: {
    "PORT": 9892,
    "CI": 1,
    "NUXT_TELEMETRY_DISABLED": 1
  }
}

We are running out of ideas and this only happens in production, making it extremely hard to debug and we are scoping the problem down to the server configuration.

We understand that this question might be tagged as off-topic since it's not too specific but what I'm looking for are some ideas on things that might help debug this issue. The webapp is done using Quasar framework in SSR mode and we are using https://cleavr.io/ to deploy our application.

We have tried following this guide on Quasar's website to debug hydration errors but haven't gotten us anywhere.

In case you would like to reproduce the bug, you will need to sign up to an account in codotto.com, then visit https://codotto.com so that you are redirected to the dashboard instead of the landing page.

Can anyone here help or explain why we have these hydration errors?


Solution

  • The problem was not related to caching or any other issues we thought it was related.

    In one of our bootfiles we had the following:

    export default boot(({ router }) => {
      router.beforeEach((to, from, next) => {
        const requiresAuthentication = to.matched.some(
          (record) => record.meta.needsAuthentication
        );
        const appStore = useAppStore();
    
        if (requiresAuthentication && !appStore.isLoggedIn) {
          next({ name: 'auth-login' });
        } else {
          const onlyGuestCanSee = to.matched.some(
            (record) => record.meta.onlyGuestCanSee
          );
    
          if (onlyGuestCanSee && appStore.isLoggedIn) {
            next({ name: 'dashboard' });
          } else {
            next();
          }
        }
      });
    });
    

    In this file we didn't pass the store to useAppStore causing the request pollution and, consequently, hydration errors. The fix was to pass store to useAppStore:

    export default boot(({ router, store }) => {
      const appStore = useAppStore(store);
    
      ...
    })