restnuxt3.jsstatic-site-generationnuxt.config.js

Nuxt3 config to fetch the data from rest api and generate static page based on fetched data


I'm trying to generate a static page with nuxt 3 but no luck. I fetch the data from wordpress rest api (https://172.27.0.4/wp-json/...), nuxt works on http://0.0.0.0:3000, so I added this to nuxt.config.ts to solve CORS:

  nitro: {
    devProxy: {
      '/wp-json': {
        target: process.env.API_URL + '/wp-json',
        changeOrigin: true,
        secure: false,
      },
    },
  },

With this I can see the data from 172.27.0.4/wp-json/... on this address: http://0.0.0.0:3000/wp-json/....

And here's my /pages/index.vue:

<template>
  <div class="work-tiles">
    <div v-for="post in posts" :key="post.id">
      {{post.title}}
    </div>
  </div>
</template>

<script setup>
import { useAsyncData } from 'nuxt/app'
const { data: posts } = useAsyncData('posts', () => $fetch('http://0.0.0.0:3000/wp-json/sar/v2/work/posts'));
console.log(posts.value)
</script>

With console.log(posts) I can see the data in browser console, but I see null in the terminal. I thought I would see an array in the terminal too... If you know why, please let me know.

By the way, I don't know how to modify nuxt.config to get rid of http://0.0.0.0:3000 from $fetch('http://0.0.0.0:3000/wp-json/sar/v2/work/posts')) to make it look like: $fetch('/wp-json/sar/v2/work/posts')) and still fetch the data from the wordpress. Perhaps this is the reason of my issues...

My full nuxt.config.ts:

export default defineNuxtConfig({
  devtools: {enabled: true},
  nitro: {
    devProxy: {
      '/wp-json': {
        target: process.env.API_URL + '/wp-json',
        changeOrigin: true,
        secure: false,
      },
    },
  },
  target: 'static',
  generate: {
    routes: ['/'],
  },
  compatibilityDate: '2024-11-16',
});

Here's the command I use to generate a static page: npx nuxi generate

It makes .output directory, I open index.html in there hopefully to find posts titles in html or fetched data there, but there are empty div and error (couldn't fetch):

empty div and failed to fetch error

But using npm run dev I can see the data and html from the source code pressing (CTRL + U) in chrome.

Where am I wrong?

UPDATE:

to see fetched data in the terminal on console.log(posts.value) I had to add await to useAsyncData:

const { data: posts } = await useAsyncData('posts', () => $fetch('http://0.0.0.0:3000/wp-json/sar/v2/work/posts'));

UPDATE 2:

There's something on my side. I tried a fake api const { data: posts } = await useAsyncData('posts', () => $fetch('https://jsonplaceholder.typicode.com/todos/')); and the page successfully generated without any specific nuxt.config.ts:

export default defineNuxtConfig({
  compatibilityDate: '2024-11-16',
  nitro: {
    prerender: {
      routes: ['/'], //doesn't play a big role
    },
  },
});

Solution

  • The reason was really on my side and related to docker networking. I am using docker-compose.yml for wordpress (db, nginx, php) and added an explicit ipv4 address for each service. Nuxt is running as a container as well and in the same network as the other services. I removed explicit ip addresses and fetched the data like this:

    1. Using this variant you don't need to use the same network as nginx container:

      const { data: posts } = await useAsyncData('posts', () => $fetch('http://192.168.88.180:8080/wp-json/sar/v2/work/posts'));

    or

    1. Using this variant you'll need to use the same network as wordpress

      const { data: posts } = await useAsyncData('posts', () => $fetch('http://swp_nginx/wp-json/sar/v2/work/posts'));

    where swp_nginx is a container name.

    But I still don't know how to modify nuxt.config to fetch the data without domain: ...$fetch('/wp-json/sar/v2/work/posts')....

    Previously I used pure vue 3 with this vite.config and data fetching worked well without domain:

    server: {
      host: '0.0.0.0',
      port: 3000,
      proxy: {
        '/wp-json': {
          target: process.env.API_URL, // http://<container-name>
          changeOrigin: true,
          secure: false,
        },
      },
    },