Generating static site using Nuxt 3 and Storyblok using Netlify

280 views Asked by At

I am trying to build a static site using Nuxt 3 and I want the site to be 100% static, without any API calls.

To achieve this I have created my nuxt.config.ts file as follows.

// only showing relevant configs
export default defineNuxtConfig({
  target: 'static',
  ssr: true,
  hooks: {
    async 'nitro:config'(nitroConfig) {
      if (!nitroConfig || nitroConfig.dev) {
        return
      }
      const token = process.env.STORYBLOK_API_TOKEN;

      let cache_version = 0

      // other routes that are not in Storyblok with their slug.
      let routes = ['/'] // adds home directly but with / instead of /home
      try {
        const result = await fetch(`https://api-us.storyblok.com/v2/cdn/spaces/me?token=${token}`)

        if (!result.ok) {
          throw new Error('Could not fetch Storyblok data')
        }
        // timestamp of latest publish
        const space = await result.json()
        cache_version = space.space.version

        // Recursively fetch all routes and set them to the routes array
        await fetchStories(routes, cache_version)
        // Adds the routes to the prerenderer
        nitroConfig.prerender.routes.push(...routes)
      } catch (error) {
        console.error(error)
      }
    },
  },
})

async function fetchStories(routes: string[], cacheVersion: number, page: number = 1) {
  const token = process.env.STORYBLOK_API_TOKEN
  const version = 'published'
  const perPage = 100

  try {
    const response = await fetch(
        `https://api-us.storyblok.com/v2/cdn/links?token=${token}&version=${version}&per_page=${perPage}&page=${page}&cv=${cacheVersion}`,
    )
    const data = await response.json()
    const toIgnore = ['home']
    // Add routes to the array
    Object.values(data.links).forEach(link => {
      if (!toIgnore.includes(link.slug)) {
        routes.push('/' + link.slug)
      }
    })

    // Check if there are more pages with links

    const total = response.headers.get('total')
    const maxPage = Math.ceil(total / perPage)

    if (maxPage > page) {
      await fetchStories(routes, cacheVersion, ++page)
    }
  } catch (error) {
    console.error(error)
  }
}

My build status on Netlify is npm run generate with Publish directory as dist.

And in my components, I am using only useAsyncStoryblok

const resp = await useAsyncStoryblok(`home`, {
  version: "draft",
  resolve_relations: 'FeaturedProjects.projects',
});
projects = resp?.value?.content?.body[0]['projects']

When I do npm run generate && npm run preview

Every time any data is loaded for the first time my API is called which I don't want. Although there are no API calls after the first fetch, I am trying to achieve 0 API calls to fetch content.

I am trying to achieve the following.

  1. The site should generate all the HTML in the building phase
  2. No API calls, and the .html files should have all the data static for better SEO.

I am also concerned about my API request limit being reached if api keeps getting called.

What am I doing wrong here?

1

There are 1 answers

0
Mohammad Hosseini On

If you want to ensure that your Nuxt 3 static site is truly static and doesn't make any API calls during runtime, you need to avoid using dynamic data fetching methods like useAsyncStoryblok on the client side.

Here are some suggestions to help you achieve your goal:

1-Static Content Generation: Make sure that you are utilizing Nuxt 3's Static Site Generation (SSG) properly. This ensures that your pages are pre-rendered during the build phase, and the resulting HTML files should contain all the necessary data.

Ensure your nuxt.config.js is configured for SSG:

export default {
  ssg: true,
  // Other Nuxt config options...
}

Also, make sure that the components/pages fetching data are using fetch or asyncData during the build process.

2-Avoid Client-Side Data Fetching: If you're using useAsyncStoryblok or any other dynamic data fetching method in your components, it might be making API calls during the client-side hydration. To avoid this, you should conditionally fetch data only during the build process.

Example using asyncData:

<template>
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>

<script setup>
export default {
  async asyncData({ params }) {
    // Fetch data during build
    const response = await fetchData(params.id);
    return { title: response.title };
  }
}
</script>

3-Check API Calls during Build: During the build process, you can check whether API calls are being made. Use the nuxt generate command and monitor the output for any unexpected API calls. If you find any, review your components and ensure that data fetching is only happening during the build.

4-Static Data Import: If your data is relatively static and doesn't change frequently, consider importing the data directly into your components instead of fetching it during runtime. This way, the data becomes part of the static build.

Example:

<script setup>
import myData from '~/static/data/myData.json';

export default {
  data() {
    return {
      title: myData.title,
      // Other data...
    };
  }
}
</script>

By following these suggestions, you should be able to create a Nuxt 3 static site that doesn't make any API calls during runtime and has all the necessary data pre-rendered during the build phase.