npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unplugin-convention-routes

v0.0.3

Published

File system base router plugin for unplugin

Downloads

239

Readme

🔥 基于文件系统的约定式路由解决方案。

🔥 基于 unplugin 开发,支持 ViteRspack 构建工具,同时支持 ReactVue 框架。

⚡️ 使用 import.meta.glob (Vite) 和 import.meta.webpackContext (Rspack) 实现零运行时依赖,自动支持 HMR。


📦 安装

pnpm i unplugin-convention-routes

🚀 使用

Vite

// vite.config.ts
import Pages from "unplugin-convention-routes/vite"

export default defineConfig({
  plugins: [
    Pages({ resolver: "vue" }), // 或 'react'
  ],
})

Rspack

// rsbuild.config.ts
import Pages from "unplugin-convention-routes/rspack"

export default defineConfig({
  tools: {
    rspack: {
      plugins: [
        Pages({ resolver: "vue" }), // 或 'react'
      ],
    },
  },
})

📖 路由约定

文件命名规则

| 文件名 | 路由路径 | | ------------------- | ----------------- | | index.vue | / | | about.vue | /about | | about/index.vue | /about | | blog/[id].vue | /blog/:id | | blog/[...all].vue | /blog/:all(.*)* |

Vue 使用

// env.d.ts
/// <reference types="unplugin-convention-routes/client-vue" />
import { createRouter, createWebHistory } from "vue-router"
// main.ts
import routes from "~pages"

const router = createRouter({
  history: createWebHistory(),
  routes,
})

React 使用

// env.d.ts
/// <reference types="unplugin-convention-routes/client-react" />
import { BrowserRouter, useRoutes } from "react-router-dom"
// main.tsx
import routes from "~react-pages"

function App() {
  return useRoutes(routes)
}

createRoot(document.getElementById("root")!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)

⚙️ 配置选项

完整类型定义

interface UserOptions {
  /** 路由解析器类型(必填) */
  resolver: "vue" | "react"
  /** 页面目录配置 */
  dirs?: string | PageDir[]
  /** 文件扩展名 */
  extensions?: string[]
  /** 排除的文件模式 */
  exclude?: string[]
  /** 导入路径风格 */
  importPath?: "absolute" | "relative"
  /** 路径大小写敏感 */
  caseSensitive?: boolean
  /** 路由名称分隔符 */
  routeNameSeparator?: string
  /** 扩展路由配置的钩子函数 */
  extendRoute?: (route: any, parent: any | undefined) => any | void
  /** 路由生成后的钩子函数 */
  onRoutesGenerated?: (routes: any[]) => Awaitable<any[] | void>
  /** 客户端代码生成后的钩子函数 */
  onClientGenerated?: (clientCode: string) => Awaitable<string | void>
}

interface PageDir {
  /** 目录路径 */
  dir: string
  /** 基础路由前缀 */
  baseRoute?: string
  /** 文件匹配模式 */
  filePattern?: string
}

基础配置选项

| 选项 | 说明 | 默认值 | | -------------------- | ------------------------------- | ---------------------------------------------------------------- | | resolver | 框架类型,支持 vuereact | 必填 | | dirs | 页面目录配置,支持字符串或数组格式 | 'src/pages' | | extensions | 文件扩展名列表 | Vue: ['vue', 'ts', 'js'] / React: ['tsx', 'jsx', 'ts', 'js'] | | exclude | 排除的文件模式列表 | ['node_modules', '.git', '**/__*__/**', '**/components/**', '**/components.*'] | | caseSensitive | 路径是否大小写敏感 | false | | routeNameSeparator | 路由名称分隔符 | '-' | | importPath | 导入路径风格,absoluterelative | 'relative' |


resolver(必填)

指定路由解析器类型,决定生成的路由代码格式。

Pages({
  resolver: "vue", // 生成 Vue Router 格式的路由
})

Pages({
  resolver: "react", // 生成 React Router 格式的路由
})

dirs

配置页面目录,支持字符串或数组格式。

单目录配置(字符串)

Pages({
  resolver: "vue",
  dirs: "src/pages", // 默认值
})

多目录配置(数组)

当项目有多个页面目录时,可以使用数组配置:

Pages({
  resolver: "vue",
  dirs: [
    // 主页面目录
    { dir: "src/pages", baseRoute: "" },
    // 功能模块页面目录,所有路由添加 /features 前缀
    { dir: "src/features/**/pages", baseRoute: "features" },
    // 管理后台页面目录,所有路由添加 /admin 前缀
    { dir: "src/admin/pages", baseRoute: "admin" },
  ],
})

PageDir 配置项说明:

| 属性 | 说明 | 示例 | | ------------ | -------------------- | ----------------------- | | dir | 目录路径,支持 glob 模式 | 'src/pages' | | baseRoute | 基础路由前缀,所有路由会添加此前缀 | 'admin'/admin/... | | filePattern | 文件匹配模式,用于进一步筛选文件(可选) | '**/*.vue' |


extensions

指定要识别的文件扩展名。

Pages({
  resolver: "vue",
  extensions: ["vue"], // 只识别 .vue 文件
})

Pages({
  resolver: "react",
  extensions: ["tsx", "jsx"], // 只识别 .tsx 和 .jsx 文件
})

exclude

排除不需要生成路由的文件或目录。支持基本的 glob 模式匹配。

支持的通配符:

| 通配符 | 说明 | 示例 | | ------ | ---- | ---- | | ** | 匹配任意层级的目录和文件 | **/components/** 匹配任意层级的 components 目录 | | * | 匹配单个路径段中的任意字符(不包括 /) | *.test.* 匹配 foo.test.ts | | ? | 匹配单个字符(不包括 /) | file?.vue 匹配 file1.vue |

⚠️ 注意:不支持 minimatch 的高级功能,如否定模式 !、花括号扩展 {a,b} 等。

默认排除列表:

  • node_modules - 依赖目录
  • .git - Git 目录
  • **/__*__/** - 测试相关目录(如 __tests____mocks__
  • **/components/** - components 目录
  • **/components.* - components 文件(如 components.vuecomponents.tsx
// 自定义排除列表(会覆盖默认值)
Pages({
  resolver: "vue",
  exclude: [
    "node_modules",
    ".git",
    "**/__*__/**",
    "**/components/**",
    "**/*.test.*", // 排除测试文件
    "**/*.spec.*",
  ],
})

importPath

控制组件导入路径的风格。

| 值 | 说明 | 示例 | | ----------- | ------------------------ | ----------------------------------------- | | 'relative' | 相对路径(默认) | './pages/index.vue' | | 'absolute' | 绝对路径(基于项目根目录) | '/src/pages/index.vue' |

Pages({
  resolver: "vue",
  importPath: "absolute", // 使用绝对路径
})

caseSensitive

控制路由路径是否大小写敏感。

Pages({
  resolver: "vue",
  caseSensitive: true, // /About 和 /about 是不同的路由
})

routeNameSeparator

设置路由名称的分隔符,用于从文件路径生成路由名称。

// 文件路径: src/pages/blog/[id].vue
// 默认分隔符 '-': 路由名称为 'blog-id'

Pages({
  resolver: "vue",
  routeNameSeparator: "_", // 路由名称变为 'blog_id'
})

高级钩子函数

extendRoute

扩展或修改单个路由配置。在每个路由生成时调用。

Pages({
  resolver: "vue",
  extendRoute: (route, parent) => {
    // 为所有路由添加 meta 信息
    route.meta = {
      ...route.meta,
      title: route.name,
    }

    // 为特定路由添加额外配置
    if (route.path === "/admin") {
      route.meta = { requiresAuth: true }
    }

    // 返回修改后的路由(或返回 void 保持原引用)
    return route
  },
})

参数说明:

  • route - 当前路由配置对象
  • parent - 父路由配置(如果是嵌套路由)

onRoutesGenerated

在所有路由生成完成后调用,可以批量修改路由数组。

Pages({
  resolver: "vue",
  onRoutesGenerated: async (routes) => {
    // 添加全局路由(如 404 页面)
    routes.push({
      path: "/:pathMatch(.*)*",
      name: "NotFound",
      component: () => import("./src/pages/404.vue"),
    })

    // 过滤掉某些路由
    return routes.filter(route => !route.path.startsWith("/draft"))
  },
})

onClientGenerated

在客户端代码生成完成后调用,可以修改最终生成的代码字符串。

Pages({
  resolver: "vue",
  onClientGenerated: (clientCode) => {
    // 在代码开头添加注释
    const header = "// 自动生成的路由文件,请勿手动修改\n"
    return header + clientCode
  },
})

🔨 示例项目

友情链接