Using MirageJS with Nuxt

brattonross

brattonross

Posted on March 1, 2020

Using MirageJS with Nuxt

Update 11th March 2020

If you are running Nuxt in universal mode you can still take advantage of Mirage by ensuring that you only make api calls on the client side. If you attempt to make api calls from the server-side then Mirage won't be able to capture them, as it only runs in the browser.

If you don't need to make use of Nuxt's asyncData method and you are just going to make your api calls in a lifecycle hook like created, then you just need to check that your code is running on the client-side first:

async created() {
  if (process.client) {
    const response = await this.$axios.get('/api/stuff')
  }
}

Otherwise, we find ourselves in a bit of a situation. If we want to use asyncData, then the issue we have is that the initial call will be made on the server-side. All subsequent route changes are client-side, so Mirage will work in asyncData on every route change aside from the initial request to our app.

One quick hacky way to get around this is to use the created hook for the initial render, and then asyncData on every other call.

const isDevelopment = process.env.NODE_ENV === 'development'

export default {
  async asyncData({ $axios }) {
    // If we're in development mode and running this 
    // code on the server-side, then return early
    if (isDevelopment && !process.client) {
      return
    }

    const { data } = await $axios.get('/api/stuff')
    return {
      data,
      // Set this so that subsequent calls to the
      // `created` hook don't make the api call
      initialCallDone: true
    }
  },

  data() {
    return {
      initialCallDone: false
    }
  },

  async created() {
    // Only make this api call when we're in development mode,
    // it isn't the initial call to the app,
    // and we're running the code on the client-side
    if (isDevelopment && !this.initialCallDone && process.client) {
      await this.$axios.get('/api/stuff')
    }
  }
}

I recently learnt about MirageJS, a library that helps you build out and test a frontend app without having an api in place. The best thing about this library in my opinion is how it hijacks the browser's network requests, so you can continue using exactly the same code for interacting with Mirage and your real api.

When integrating this into a Nuxt app, I soon stumbled upon some issues. Making an HTTP request that Mirage should have been able to handle would throw a 404:

Nuxt Server Error

At this point I was running my app in universal mode, since for my production site I wanted to make use of Nuxt's SSR capabilities. I tried switching Nuxt over to spa mode to see if the issue was caused by using universal mode, and voila! Switching Nuxt to spa mode allows Mirage to work as expected. I'm using the following code to run my app in spa mode during development, but then switching to universal mode for production, where I don't depend on Mirage:

// nuxt.config.js

export default {
  mode: process.env.NODE_ENV === 'development' ? 'spa' : 'universal'
}

There seems to be some underlying conflict between Nuxt and Mirage when running in universal mode. I'm no expert in either of these technologies, so I can't say where the issue lies, but this workaround is suitable for me and perhaps it will help some others too.

💖 💪 🙅 🚩
brattonross
brattonross

Posted on March 1, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related