Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SWR (and ISR) not working locally #28212

Open
AdrianFahrbach opened this issue Jul 18, 2024 · 2 comments
Open

SWR (and ISR) not working locally #28212

AdrianFahrbach opened this issue Jul 18, 2024 · 2 comments

Comments

@AdrianFahrbach
Copy link

AdrianFahrbach commented Jul 18, 2024

Environment

  • Operating System: Darwin
  • Node Version: v20.15.0
  • Nuxt Version: 3.12.3
  • CLI Version: 3.12.0
  • Nitro Version: 2.9.7
  • Package Manager: [email protected]
  • Builder: -
  • User Config: modules, routeRules, nitro, compatibilityDate
  • Runtime Modules: @nuxt/[email protected]
  • Build Modules: -

Reproduction

Github repo: https://github.com/AdrianFahrbach/nuxt-swr-test

I tested with this repo by following these steps:

  1. Run npm install
  2. Build the app with npm run build
  3. Preview the app with npm run preview
  4. Open http://localhost:3000/page-1 to test the SWR behaviour

Describe the bug

SWR and ISR doesn't seem to work when testing the build locally. Whatevery I try the pages are either completely static or regular SSR on each load.

My testing setup

In my test repository I got three pages (/page-1, /page-2 and /page-3) that all are set as swr pages with a lifespan of 10 seconds. My nuxt config basically looks like this:

export default defineNuxtConfig({
  routeRules: {
    '/**': { swr: 10 },
  },
  nitro: {
    prerender: {
      routes: ['/page-1', '/page-2', '/page-3'],
    },
    routeRules: {
      '/**': { swr: 10 },
    },
  },
});

All of those routes are catched (and validated) in pages/[...slug].vue. This component also gets a current timestamp from an external API using fetch in an useAsyncStorage hook. That looks like this:

const { data: apiResponse } = await useAsyncData(slugString, () => {
  return fetch('https://worldtimeapi.org/api/timezone/utc').then(res => res.json());
});

The response of that call includes a timestamp which gets displayed on the page. In addition to that I also calculate the seconds from now to the timestamp retrieved during SSR. My full component basically looks like this:

<template>
  <div>
    <p>Generation timestamp: {{ generatedUtcTime }}</p>
    <p>Generated seconds ago: {{ secondsAgo }}</p>
  </div>
</template>

<script setup lang="ts">
definePageMeta({
  validate: async route => {
    const slugString = typeof route.params.slug === 'string' ? route.params.slug : route.params.slug.join('/');
    return ['page-1', 'page-2', 'page-3'].includes(slugString);
  },
});

const route = useRoute();
const slugString = typeof route.params.slug === 'string' ? route.params.slug : route.params.slug.join('/');

const { data: apiResponse } = await useAsyncData(slugString, () => {
  return fetch('https://worldtimeapi.org/api/timezone/utc').then(res => res.json());
});

const generatedUtcTime = apiResponse.value!.utc_datetime;
const secondsAgo = ref();

onMounted(() => {
  secondsAgo.value = Math.round((new Date().getTime() - new Date(generatedUtcTime).getTime()) / 1000);
});
</script>

To test SWR I build the app using nuxt build and preview it using nuxt preview.

Expected behaviour

When previewing my application I expect it to behave (as close as possible) as it would in an production environment. In this case I expect the timestamp to change every 10 seconds, since my pages should get stale after 10 seconds and then refresh the server side data fetch from useAsyncData. useAsyncData should also only be running on the server similar to Next.js getStaticProps or getServerSideProps.

Current behaviour

When opening the pages the timestamp doesn't change but instead always stays the same as it was during build.

Additional context

#18787 Static and SWR rendering not working
This issue has a discussion about a similar problem, however the suggested solutions here didn't help me and there is no mention of local testing.

#9474 SSR asyncData issue: rendering on client instead of server
#27840 nuxtlink or navigateto forces client side request instead of SSR
On a different project it got SWR without revalidation working (so basically static). The problem there was that useAsyncData was then running on the client when navigating with a Nuxt link. I'm not quite sure if this is intentional, since I personally wouldn't expect useAsyncData to run on the client and therefore this may be related to this.

@danielroe
Copy link
Member

In order for swr to work, you should not prerender them. Prerendering the pages entirely bypasses dynamic caching rules.

@AdrianFahrbach
Copy link
Author

In order for swr to work, you should not prerender them. Prerendering the pages entirely bypasses dynamic caching rules.

Thanks a lot, that made it work!
Two extra questions though:

  1. That also means that I can't have SSR/ISR routes prerendered for production and the first view will always be slow, right? I adjusted my test repo to add a 5 seconds delay to the useAsyncData hook and now the first view takes 5 seconds.

  2. I got the same "issue" as mentioned in nuxtlink or navigateto forces client side request instead of SSR #27840 and Force useFetch or useAsyncData to run on server-side #21456 that useAsyncData runs on the client when navigating with NuxtLink. I added a comment in nuxtlink or navigateto forces client side request instead of SSR #27840 here, to keep that discussion where it should be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants