跳转到内容

路径匹配规则

本章节详细介绍 vite-plugin-mock-dev-server 中的路径匹配机制,帮助你精确控制哪些请求应该被 Mock。

概述

插件使用 path-to-regexp 库进行路径匹配,这是 Express 和 Koa 等主流框架使用的同款库,提供了强大而灵活的路径匹配能力。

基础匹配规则

静态路径匹配

最简单的匹配方式,URL 必须完全匹配:

ts
export default defineMock({
  url: '/api/users', // 只匹配 /api/users
  body: { list: [] }
})
请求 URL是否匹配
/api/users✅ 匹配
/api/users/❌ 不匹配(注意尾部斜杠)
/api/users/123❌ 不匹配
/API/users❌ 不匹配(大小写敏感)

动态参数匹配

使用 :paramName 语法捕获 URL 中的动态部分:

ts
export default defineMock({
  url: '/api/users/:id',
  body: ({ params }) => ({
    userId: params.id // 获取捕获的参数
  })
})
请求 URL是否匹配params 值
/api/users/123✅ 匹配{ id: '123' }
/api/users/abc✅ 匹配{ id: 'abc' }
/api/users❌ 不匹配-
/api/users/123/posts❌ 不匹配-

多个动态参数

可以在一个 URL 中定义多个参数:

ts
export default defineMock({
  url: '/api/users/:userId/posts/:postId',
  body: ({ params }) => ({
    userId: params.userId,
    postId: params.postId
  })
})
请求 URLparams 值
/api/users/1/posts/100{ userId: '1', postId: '100' }

高级匹配规则

可选参数

使用 {} 包裹参数标记为可选:

ts
export default defineMock({
  url: '/api/users{/:id}',
  body: ({ params }) => {
    if (params.id) {
      return { type: 'single', id: params.id }
    }
    return { type: 'list', users: [] }
  }
})
请求 URL是否匹配params 值
/api/users✅ 匹配{}
/api/users/123✅ 匹配{ id: '123' }

通配符匹配

使用 *name 语法匹配一个或多个路径段:

ts
export default defineMock({
  url: '/api/files/*path',
  body: ({ params }) => ({
    path: params.path // 数组形式
  })
})
请求 URLparams.path
/api/files/docs['docs']
/api/files/docs/guide.md['docs', 'guide.md']

零个或多个匹配

如需匹配零个或多个路径段,请使用可选组包裹通配符:

ts
export default defineMock({
  url: '/api/files{/*path}',
  body: ({ params }) => ({
    path: params.path || [] // 可能是 undefined 或数组
  })
})
请求 URLparams.path
/api/filesundefined
/api/files/docs['docs']

任意路径匹配

使用通配符匹配任意路径:

ts
export default defineMock({
  url: '/api/proxy/*path',
  body: ({ params }) => ({
    proxiedPath: params.path?.join('/') // 使用数组方法访问
  })
})
请求 URLparams.path
/api/proxy/anything['anything']
/api/proxy/a/b/c['a', 'b', 'c']

前缀匹配(正则形式)

在插件配置中使用 ^ 开头表示正则匹配:

ts
mockDevServerPlugin({
  prefix: [
    '/api', // 字符串前缀
    '^/api/v\\d+/.*', // 正则:匹配 /api/v1/, /api/v2/ 等
    '^/graphql$' // 正则:精确匹配 /graphql
  ]
})

路径匹配优先级

当多个 Mock 配置匹配同一个请求时,插件按以下规则确定优先级:

默认优先级规则

  1. 静态路径 > 动态参数 - /api/users 优先于 /api/:id
  2. 更少参数 > 更多参数 - /api/a/:b 优先于 /api/:a/:b
  3. 定义顺序 - 相同优先级时,先定义的优先

示例

ts
export default defineMock([
  {
    url: '/api/users', // 优先级 1:静态路径
    body: 'all users'
  },
  {
    url: '/api/users/:id', // 优先级 2:一个动态参数
    body: 'single user'
  },
  {
    url: '/api/:resource/:id', // 优先级 3:两个动态参数
    body: 'generic resource'
  }
])
请求 URL匹配的配置
/api/users/api/users
/api/users/123/api/users/:id
/api/posts/123/api/:resource/:id

自定义优先级

当默认规则无法满足需求时,可以使用 priority 配置:

ts
mockDevServerPlugin({
  priority: {
    // 全局优先级:按顺序排列,靠前的优先级更高
    global: [
      '/api/users/admin', // 最高优先级
      '/api/users/:id',
      '/api/:resource/:id'
    ],
    // 特殊优先级规则
    special: {
      '/api/:a/:b/c': {
        rules: ['/api/a/:b/:c'], // 当与这些规则冲突时
        when: ['/api/a/b/c'] // 在这些场景下
      }
    }
  }
})

实际应用场景

场景 1:RESTful API 设计

ts
export default defineMock([
  // 列表和创建
  {
    url: '/api/users',
    method: 'GET',
    body: { users: [] }
  },
  {
    url: '/api/users',
    method: 'POST',
    body: ({ body }) => ({ id: Date.now(), ...body })
  },
  // 单个资源操作
  {
    url: '/api/users/:id',
    method: 'GET',
    body: ({ params }) => ({ id: params.id })
  },
  {
    url: '/api/users/:id',
    method: 'PUT',
    body: ({ params, body }) => ({ id: params.id, ...body })
  },
  {
    url: '/api/users/:id',
    method: 'DELETE',
    status: 204
  },
  // 嵌套资源
  {
    url: '/api/users/:userId/posts',
    body: ({ params }) => ({ userId: params.userId, posts: [] })
  }
])

场景 2:文件服务

ts
export default defineMock([
  {
    url: '/api/files/:type(images|documents|videos)/:name',
    body: ({ params }) => ({
      type: params.type,
      filename: params.name
    })
  },
  {
    url: '/api/download/*path',
    response: (req, res) => {
      const filePath = req.params.path?.join('/')
      // 处理文件下载...
    }
  }
])

场景 3:版本控制 API

ts
mockDevServerPlugin({
  prefix: [
    '^/api/v\\d+/.*' // 匹配所有版本化的 API
  ]
})

export default defineMock([
  {
    url: '/api/v1/users',
    body: { version: 'v1', users: [] }
  },
  {
    url: '/api/v2/users',
    body: { version: 'v2', users: [], meta: {} }
  }
])

注意事项

  1. 大小写敏感: URL 匹配是大小写敏感的,/api/Users/api/users 是不同的路径
  2. 尾部斜杠: /api/users/api/users/ 被视为不同路径
  3. 参数类型: 所有参数值都是字符串,需要手动转换为数字或其他类型

从旧版本迁移

path-to-regexp v8.x 与旧版本相比有以下破坏性变更:

旧版本语法v8.x 语法说明
:param?{/:param}可选参数使用花括号包裹
:param*{/*param}零个或多个使用可选组+通配符
:param+/*param一个或多个使用通配符
(.*)/*param通配符使用命名参数形式

调试技巧

开启调试日志查看匹配过程:

ts
mockDevServerPlugin({
  log: 'debug' // 启用详细日志
})

在控制台中你将看到:

  • 请求路径
  • 尝试匹配的规则
  • 最终匹配的结果

这有助于排查路径匹配问题。

基于 MIT 许可发布