0

I have a weird thing in a Nuxt project whereby an asyncData callback is first fired client-side, when the page is first visited (by clicking a nuxt-link link), and then on server-side when the page is refreshed or visited manually (i.e. via a URL).

This is obviously not desirable; the request should be sent server-side only - and indeed will fail on the client due to CORS.

Here's my Nuxt config:

export default {

    target: 'server',
    ssr: true,
    head: {
        meta: [
            {charset: 'utf-8'},
            {name: 'viewport', content: 'width=device-width, initial-scale=1'}
        ],
        titleTemplate: 'Rescue Partners%s'
    },
    css: [
        '~/assets/css/buefy-init.scss',
        '~/assets/css/main.scss'
    ],
    components: true,
    buildModules: [
        '@nuxtjs/style-resources',
        '@nuxtjs/google-fonts'
    ],
    modules: [
        ['nuxt-buefy', {css: false}],
    ],
    build: {},

    //style resources (global SASS vars)
    styleResources: {
        scss: ['~/assets/css/project-vars.scss']
    },

    //Google fonts
    googleFonts: {
        families: {
            'M PLUS Rounded 1c': [700]
        }
    }

}

And here's the asyncData callback in the page in question:

    //async data...
async asyncData(ctx) {

    let merge = {};

    //...groups (for filter)
    const at = ctx.route.params.animalType;
    let bGroups = await apiReq.call(ctx, 'cache', 'breedGroups', {
        at: at.replace(/s$/, '')
    });
    if (bGroups == null) return;
    merge.filters = ctx.store.getters.getFilters(at, bGroups);
    return merge;
},

(apiReq is a util which fires a fetch() request.)

  • Hi, not sure how we can help you here. Please provide some code, [repro] or a Github repo. – kissu May 21 '22 at 14:54
  • I'll try to put a minimal example together but obviously I can't share my whole project so I'll have to see if I can boil it down to a skeleton project that has the issue. – user9540234 May 24 '22 at 17:53
  • Yes, exactly that please. – kissu May 24 '22 at 17:54
  • @kissu I've narrowed this down a bit. It's not a 404 - it's an error being thrown. What's happening is, for some reason, when you first visit the link (by clicking a link), my `asyncData` callback is happening client-side. That fails, as it should, due to CORs. When you refresh, the `asyncData` callback happens server-side! That succeeds, as there's no CORs in play. Why would the callback happen client-side on first visit via link, and server side on refresh/manual visit to page by entering URL? I'll edit the question to provide some info around this setup. – user9540234 May 27 '22 at 13:28
  • Simplest and cleanest fix would be to configure CORS properly here, don't you think so? – kissu May 27 '22 at 13:29
  • OK that's a surprising response. Surely we can agree it's not ideal that *sometimes* the request fires client-side and *sometimes* it fires server side? No, CORS is not the issue - this request should be fired by the server only as it involves passing credentials. It's not intended to be fired client-side. I would have thought having `target` set to "server" would ensure this. – user9540234 May 27 '22 at 13:32
  • Actually, it will fire on both all the time (supposed to at least). If it is supposed to be run on the server only, `asyncData` (isomorphic) is not the place for that but rather `nuxtServerInit`. Please check the lifecycle to see which hooks are called on the server, client or both: https://nuxtjs.org/pt/docs/concepts/nuxt-lifecycle#nuxt-lifecycle – kissu May 27 '22 at 13:41
  • And no `target: 'server'` only generates the pages on demand via a Node.js server, it doesn't mean that it is making calls only on the server. Nuxt is basically a Vue app on steroids, but after the initial render (on the server), the rest is done on the client side only. – kissu May 27 '22 at 13:43
  • A more details answer can be found here: https://stackoverflow.com/a/72406663/8816585 – kissu May 27 '22 at 14:07
  • Interesting! So I'm using the wrong part of the life cycle. You say it will fire on both all the time - yet for me, it fires on one OR the other. If I put a `console.log()` in my callback, I see it EITHER in the terminal (refresh) or in the browser console (link visit). Similarly, in the former case, I don't see the request show up in the browser's network log, but I do in the latter. Anyway, I'll switch to `nuxtServerInit`. Presumably that will involve refactoring how I merge the data into the component. – user9540234 May 27 '22 at 14:12
  • As I said, the initial render is always on the server and also, `asyncData` is a hook that is triggered upon **client side** navigation hence why you may see some differences. Keep in mind that some `console.log` will be output in your browser console and some other in your terminal. (`fetch()` hook is a bit simpler on that aspect) There is also the fact that when you're running your server locally in `dev` mode, it behaves a bit differently because of the webpack dev server. Quite tricky I know. Good luck with your refacto, please keep me updated. – kissu May 27 '22 at 14:26
  • Thanks again for your help. The fact that you can't force Nuxt to do some operations on the server was a bit mind-blowing for me. In the end I refactored my API to support server- and client-side requests, but it's definitely been an eye-opener. Presumably, then, Nuxt is flat-out unsuited to certain types of site where code *must* run on the server, and on each and every page load / route change. – user9540234 Jun 16 '22 at 11:11

0 Answers0