loading...

Using MirageJS with Nuxt

brattonross profile image brattonross Updated on ・3 min read

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.

Discussion

pic
Editor guide
Collapse
santigaleazzi profile image
Santiago G.

Awesome dude!! I was struggling with this since I started using Mirage.js two weeks ago.

I think Mirage is a great plugin. We need more people like you on the community.

I'll try to push a Nuxt - Mirage template so that people can use it on their projects.

Collapse
rvmourik profile image
Robbert van Mourik

Hi,

Did you ever find the time to create a template? Would really love to see that :-)

Thanks.

Collapse
martinmalinda profile image
Martin Malinda

Hey! Thanks!

Have you had success with using Mirage in tests as well? I'm just starting with it in Nuxt, and I hit a wall because with Mirage I want to have a more broad test of course, not just mock store. But then I need the VueX store in the test and probably also most of the stuff from the plugins folder.

Any insights appreciated!

Collapse
adhamfarrag profile image
Adham Farrag

Can you please create a demo? It's not working with me. Thanks. :)

Collapse
jstgermain profile image
Justin St. Germain

in nuxt.config.js, update this:
mode: "universal",

to:
mode: process.env.NODE_ENV === "development" ? "spa" : "universal",

Collapse
mohsin708961 profile image
{{7*7}}

Awesome