defineMockData
Define Mock data with a memory-based sharing mechanism, used to share state between multiple Mock files.
Problem Background
Since the plugin compiles *.mock.* files as separate entries, this leads to inconsistent dependency relationships after compilation of mock files, with each mock file having its own independent scope. Even if multiple *.mock.* files import the same data.ts file, they are completely different data instances, so operations on data cannot be shared across different *.mock.* files.
defineMockData provides a memory-based data sharing mechanism to solve this problem.
Function Signature
function defineMockData<T = any>(
key: string,
initialData: T
): MockData<T>Parameters
key
- Type:
string - Description: Unique identifier key for Mock data
- Required: Yes
initialData
- Type:
T - Description: Initial data value
- Required: Yes
options
- Type:
{ persistOnHMR?: boolean } - Description: An options object used to configure the data sharing mechanism.
- Optional: Yes
- Default Value:
{}- persistOnHMR: Whether to preserve the initial data during HMR. The default value is
false, meaning whether data will be reinitialized during HMR.
- persistOnHMR: Whether to preserve the initial data during HMR. The default value is
By default, the plugin internally determines whether data needs to be reinitialized by comparing whether the initial data has changed. However, when using libraries such as mockjs or faker, since the data is randomly generated, the plugin cannot directly determine whether the data has changed. Therefore, manual configuration of the persistOnHMR option is required.
Return Value
- Type:
MockData<T> - Description: Object containing getter, setter, and value properties
Return Value Structure
type MockData<T> = readonly [
() => T, // getter function
(val: T | ((val: T) => T | void)) => void // setter function
] & {
value: T // Directly accessible property
}Examples
Basic Usage
import { defineMockData } from 'vite-plugin-mock-dev-server'
// Define shared user data
export const users = defineMockData('users', [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
])
// Define shared post data
export const posts = defineMockData('posts', [
{ id: 1, title: 'Hello World', authorId: 1 },
{ id: 2, title: 'Getting Started', authorId: 2 }
])import { defineMock } from 'vite-plugin-mock-dev-server'
import { users } from './data'
export default defineMock([
// Get user list
{
url: '/api/users',
method: 'GET',
body: () => users.value
},
// Get single user
{
url: '/api/users/:id',
method: 'GET',
body: ({ params }) => {
return users.value.find(u => u.id === Number(params.id))
}
},
// Create user
{
url: '/api/users',
method: 'POST',
body: ({ body }) => {
const newUser = {
id: Date.now(),
...body
}
// Update data using setter
users.value = [...users.value, newUser]
return newUser
}
},
// Delete user
{
url: '/api/users/:id',
method: 'DELETE',
body: ({ params }) => {
const id = Number(params.id)
// Update using setter function form
users[1](prev => prev.filter(u => u.id !== id))
return { success: true }
}
}
])Using getter/setter Functions
import { defineMock, defineMockData } from 'vite-plugin-mock-dev-server'
const counter = defineMockData('counter', { count: 0 })
export default defineMock([
{
url: '/api/counter',
method: 'GET',
body: () => ({
count: counter[0]().count // Using getter function
})
},
{
url: '/api/counter/increment',
method: 'POST',
body: () => {
// Using setter function
counter[1](prev => ({
count: prev.count + 1
}))
return { count: counter[0]().count }
}
}
])Complex Data Operations
import { defineMock, defineMockData } from 'vite-plugin-mock-dev-server'
interface Todo {
id: number
text: string
completed: boolean
createdAt: number
}
const todos = defineMockData<Todo[]>(
'todos',
[
{ id: 1, text: 'Learn Vite', completed: false, createdAt: Date.now() },
{ id: 2, text: 'Build Mock API', completed: true, createdAt: Date.now() }
],
{ persistOnHMR: true }, // Ensure data is not reset during HMR, preserving existing data state
)
export default defineMock([
// Get todo list (supports filtering)
{
url: '/api/todos',
method: 'GET',
body: ({ query }) => {
let result = todos.value
// Filter by completion status
if (query.completed !== undefined) {
const isCompleted = query.completed === 'true'
result = result.filter(t => t.completed === isCompleted)
}
// Search by keyword
if (query.q) {
result = result.filter(t =>
t.text.toLowerCase().includes(String(query.q).toLowerCase())
)
}
return result
}
},
// Create todo
{
url: '/api/todos',
method: 'POST',
body: ({ body }) => {
const newTodo: Todo = {
id: Date.now(),
text: body.text,
completed: false,
createdAt: Date.now()
}
todos.value = [newTodo, ...todos.value]
return newTodo
}
},
// Toggle completion status
{
url: '/api/todos/:id/toggle',
method: 'PATCH',
body: ({ params }) => {
const id = Number(params.id)
todos[1](prev =>
prev.map(t =>
t.id === id ? { ...t, completed: !t.completed } : t
)
)
return todos.value.find(t => t.id === id)
}
},
// Batch delete completed
{
url: '/api/todos/clear-completed',
method: 'DELETE',
body: () => {
const completedCount = todos.value.filter(t => t.completed).length
todos[1](prev => prev.filter(t => !t.completed))
return { deleted: completedCount }
}
}
])Hot Reload Handling
defineMockData has built-in hot reload handling mechanism:
- Caching Mechanism: Data is cached to ensure multiple Mock files access the same instance
- Hot Reload Protection: During hot updates, the initial data will not be reset if it remains unchanged (however, if using
mockjsorfaker-jsto generate random data, you need to manually configurepersistOnHMRtotrue). - Data Persistence: Data state is preserved after file modification and recompilation
Important Notes
- Memory Storage: Data is only stored in memory and will be lost after service restart
- Persistence Recommendation: For persistent storage, it is recommended to use databases like
lowdb,level, etc. - Key Uniqueness: Ensure
keyis globally unique to avoid data conflicts - Data Types: It is recommended to define TypeScript interfaces for complex data to get type hints
// Persistence example (using lowdb)
import { Low } from 'lowdb'
import { JSONFile } from 'lowdb/node'
import { defineMock } from 'vite-plugin-mock-dev-server'
const adapter = new JSONFile('db.json')
const db = new Low(adapter, { posts: [] })
await db.read()
export default defineMock({
url: '/api/posts',
body: () => db.data.posts
})