Search code examples
vue.jsnuxt.jssanityasyncdata

Nuxtjs and Sanity CMS - $sanity.fetch() returns null on page change in asyncData


I'm using NuxtJS with Sanity CMS.

I've setup a few page components, of which each page component is using the asyncData hook to fetch data from the CMS to display the page.

My page components all mostly look like this, but with different groq queries:

<script>
import { groq } from '@nuxtjs/sanity';

export default {
    async asyncData({ $sanity }) {
        const query = groq`
            *[_type == "about"][0]
        `;
        const about = await $sanity.fetch(query);
        console.log(about); //returns proper data on page load, returns null on page change
        return { about };
    }
};
</script>

On initial page load or entire page refresh, the page loads just fine - for all pages in my app.

When using the local dev server, when I change pages using a <NuxtLink>, every page that follows this pattern fails to return data with the $sanity.fetch() method. Every time it returns null. This makes it really difficult for me to develop page transitions.

I can try to convert these to use the fetch hook, but AFAIK, this is the right use-case for asyncData.

In terms of versioning, here is what's in my package.json

{
    //...,
    "dependencies": {
        "@nuxtjs/sanity": "^0.9.4",
        "@nuxtjs/style-resources": "^1.2.0",
        "@nuxtjs/svg": "^0.1.12",
        "@sanity/asset-utils": "^1.1.5",
        "@sanity/client": "^2.13.0",
        "@sanity/image-url": "^0.140.22",
        "axios": "^0.21.1",
        "core-js": "^3.15.1",
        "nuxt": "^2.15.7",
        "nuxt-gsap-module": "^1.3.2",
        "vue-youtube": "^1.4.0"
    },
    "devDependencies": {
        "@babel/eslint-parser": "^7.14.7",
        "@nuxtjs/eslint-config": "^6.0.1",
        "@nuxtjs/eslint-module": "^3.0.2",
        "eslint": "^7.29.0",
        "eslint-config-prettier": "^8.3.0",
        "eslint-plugin-nuxt": "^2.0.0",
        "eslint-plugin-vue": "^7.12.1",
        "fibers": "^5.0.0",
        "prettier": "^2.3.2",
        "sass": "^1.35.2",
        "sass-loader": "^10.2.0"
    }
}

In terms of my nuxt config, here it is:

export default {
    // Target: https://go.nuxtjs.dev/config-target
    target: 'static',

    // Global page headers: https://go.nuxtjs.dev/config-head
    head: {
        titleTemplate: '%s - My great project',
        title: 'My Project',
        htmlAttrs: {
            lang: 'en'
        },
        meta: [
            { charset: 'utf-8' },
            { name: 'viewport', content: 'width=device-width, initial-scale=1' },
            { hid: 'description', name: 'description', content: '' },
            { name: 'format-detection', content: 'telephone=no' }
        ],
        link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
    },

    // Global CSS: https://go.nuxtjs.dev/config-css
    css: ['@/styles/main.scss'],

    // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
    plugins: [
        { src: '~/plugins/sanity-image-builder.js' },
        { src: '~/plugins/sanity-asset-url.js' },
        { src: '~/plugins/youtube.js', ssr: false }
    ],

    // Auto import components: https://go.nuxtjs.dev/config-components
    components: true,

    // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
    buildModules: [
        // https://go.nuxtjs.dev/eslint
        '@nuxtjs/eslint-module',
        '@nuxtjs/sanity/module',
        '@nuxtjs/style-resources',
        'nuxt-gsap-module'
    ],

    // Modules: https://go.nuxtjs.dev/config-modules
    modules: ['@nuxtjs/svg'],

    // Build Configuration: https://go.nuxtjs.dev/config-build
    build: {
        loaders: {
            scss: { sourceMap: false },
            sass: { sourceMap: false }
        }
    },

    generate: {
        fallback: true
    },

    // Override santity config here.
    privateRuntimeConfig: {
        sanity: {
            token: process.env.SANITY_TOKEN
        }
    },

    styleResources: {
        scss: ['./styles/*.scss']
    }
};


Solution

  • When you do use privateRuntimeConfig, your env variable will only be available on SSR. Hence the first time you do reach the page, you do have access for it.

    Then, when you navigate (client-side only so), you do not have access to it anymore on your client. As explained in the official documentation.

    Sanity's documentation is talking about the privateRuntimeConfig, meanwhile I do wonder if their token is aimed only for SSR or not. Usually, you do have a public token that you can expose through the publicRuntimeConfig key.

    There is a headless channel on Discord that is available here: https://discord.gg/H4hJBMCK
    Otherwise, posting a Github issue will probably lead you to an answer from Daniel.

    But it is possible that Sanity is aimed at fetching the content on server only, not sure.

    There is a setToken method but it this one is aimed at using req only, it means that this is not suited towards a target: static build?


    EDIT: nvm Ovi achieved to make it work as shown here: https://github.com/nuxt-community/sanity-module/issues/99#issuecomment-813993013
    This one should probably work!

    PS: was kinda writing as I was looking into the issues. Sorry if it's a bit messy. Tell me if the latest solution works and I'll edit my answer.