Hi everyone.
Last week I was working on a new project from scratch and encountered a common problem.
I built a big part of the frontend and my backend teammates haven't finished their part. So, I was wondering how to improve my workflow defining some mock data on frontend.
To be honest the quickly way that I usually do is to create some data in JSON format and have methods to load it, and after the API be functional I just remove the mock data to call the API.
Something like this:
./mocks/groupData.ts
import type { GroupInterface } from '../interfaces/Group'
export function getGroupData(): { groups: GroupInterface[] } {
const groups: GroupInterface[] = [
{
id: 1,
group: 'Group 1',
},
{
id: 2,
group: 'Group 2',
},
]
return { groups }
}
./screens/Groups/Groups.vue
<script setup lang="ts">
import { getGroupData } from '../../mocks/groupData'
const { groups } = getGroupData()
But after a little research I found the Mock Service Worker it's a mocking library that allows you to write client-agnostic mocks and reuse them across any frameworks, tools, and environments.
I tested on my project and it fit very well for my case, here are the steps that I used to configure the library on a Vue.js 3 project.
Step 1: Install the MSW library:
npm install msw@latest --save-dev
Step 2: Create handlers to handle the "API" requests, it will be the methods and the return of the API request:
./mocks/handlers.ts
import { http, HttpResponse } from "msw";
export const handlers = [
http.get("/users", () => {
return HttpResponse.json([
{
id: "c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d",
firstName: "John",
lastName: "Maverick",
},
{
id: "c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3e",
firstName: "Kar",
lastName: "Marx",
},
]);
}),
];
Step 3: Integrate MSW into a browser environment (other integrations are also available):
./mocks/browser.ts
// src/mocks/browser.js
import { setupWorker } from "msw/browser";
import { handlers } from "./handlers";
export const worker = setupWorker(...handlers);
Step 4: Copy the worker script to your public folder, MSW library provides a command to do this:
npx msw init <PUBLIC_DIR>
On my example I use public as a "PUBLIC_DIR", after you execute the command it will generate a file named /mockServiceWorker.js inside the public directory
Step 5: Enable mocking by calling it in main Vue.js file:
main.ts
import { createApp } from "vue";
import App from "./App.vue";
import "./assets/main.css";
async function prepareApp() {
const { worker } = await import("./mocks/browser");
return worker.start();
}
const app = createApp(App);
prepareApp().then(() => {
app.mount("#app");
});
After all this configuration you should be able to call the handler that you set before, like this:
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const users = ref<[]>([])
async function loadUserFromMsw() {
const res = await fetch('/users')
.then(response => response.json())
.then(json => {
return json
})
.catch(err => console.log('Error', err));
users.value = res
}
onMounted(async () => {
await loadUserFromMsw()
})
</script>
<template>
<main>
<pre>
{{ users }}
</pre>
</main>
</template>
My final thoughts are that I can mock various routes and methods using handlers of MSW easier than my usuall way to finish the frontend with mocking data.
If you have any suggestions, please let me know. Thank you so much for reading!
Top comments (4)
Thanks for writing this!
Looks like something got left out from this sentence:
Otherwise, a great overview of using MSW. Glad it helped you ship.
I fixed, thank you!
Great article!
When you will go to production, I suppose you will remove the public directory and disable the worker in the main vuejs file?
Was really helpful, thank you!