Search code examples
javascripthtmlvue.jsnuxt.jsserver-side-rendering

Nuxt 3 SSR does execute XHR on client side and not server side


I have started to build a Nuxt 3 project. One of the big advantages of Nuxt is that it supports SSR out of the box, which is a big plus for SEO. This is because the whole page gets rendered on the server side and the user, as well as the Googlebot, gets served a fully rendered page with all the data.

However, I am unable to set up such an infrastructure. I have coded my API backend with PHP and the Laravel framework. This is running via valet on the domain backend.test. Now I want my Nuxt 3 app to make a request to the following API endpoint https://backend.test/api/v1/products and how a list of all products being retrieved by the API.

This also works, but the point is that the user gets served an empty HTML file instead of a server side rendered HTML file which already contains the products. So, the client is actually executing the XHR request to the API endpoint. But that's not what I want to archive. I want the page to be rendered by the server.

This is my List.vue file, which should return an HTML list of all products:

<script setup>
const { data: products } = await useFetch(
  "https://backend.test/api/v1/products?order_by=newest&expired=1&type[0]=DEAL",
  {
    key: Date.now().toString(),
    server: true,
  }
);
</script>

<template>
  <div>
    <p>Product List</p>
    {{ products }}
    <!--
    <div v-if="pending" class="grid grid-cols-4 gap-5">
      <div v-for="product in products">
        <div>{{ product }}</div>
      </div>
    </div>
    <div v-else>Loading!</div>
    -->
  </div>
</template>

As you can see, I also have added the parameter server: true which is true by default to tell Nuxt explicit that he should render it on the server, but he still doesn't.

My index.vue file

<template>
  <div>
    <h1>Index</h1>
    <p>Index page</p>
    <List />
  </div>
</template>

My app.vue file:

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>

My nuxt.config.ts file:

export default defineNuxtConfig({
  modules: [
    "@nuxtjs/eslint-module",
    "@nuxtjs/tailwindcss",
    "@pinia/nuxt",
    "@nuxt/devtools",
    "@nuxtjs/html-validator",
  ],
  css: ["~/assets/css/main.scss"],
  postcss: {
    plugins: {
      tailwindcss: {},
      autoprefixer: {},
    },
  },
});

I also added ssr: true to my nuxt.config.ts file, which is already true by default, but I still see the client making the XHR request.

What am I doing wrong here?

And I also have a second question: When I remove key: Date.now().toString(), from my useFetch my data from the API is not being loaded at every page refresh but rather after like 5–10 seconds waiting. Why is that?

Kind regards


Solution

  • Finally, I have found what was causing my error. As I wrote, I have coded my backend in Laravel. My API is running with valet on a .test TLD with a self-signed HTTPS certificate provided by valet.

    Because the certificate verification by Node is unsuccessful, the server does not render the data and send an HTML document with the populated data. It simply refuses it.

    I was able to fix this problem by adding the following line to my .env file in my Nuxt 3 project:

    NODE_TLS_REJECT_UNAUTHORIZED = 0