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

@onoxm/vite-plugin-auto-router

v0.7.7

Published

a vite plugin for automatically generating react or vue route files

Readme

@onoxm/vite-plugin-auto-router

一个用于自动生成 React 或 Vue 路由文件的 Vite 插件。

English | 中文

✨ 特性

  • 自动生成路由配置,无需手动维护
  • 支持 React 和 Vue 双框架
  • 约定式路由,按目录结构自动映射
  • 支持动态路由 [id] 语法
  • home 页面路径自动转换为 /(可配置)
  • __root__ 页面作为根路由容器(可配置)
  • 可配置懒加载和热更新
  • 支持页面级配置文件
  • TypeScript 类型安全

🚀 安装

npm install -D @onoxm/vite-plugin-auto-router

📖 使用指南

页面组件判定规则

插件根据以下规则判定哪些组件是页面组件:

React 项目

  • 页面组件:在页面文件夹中使用默认导出(export default)的组件
  • 普通组件:在页面文件夹中使用具名导出(export const)的组件

Vue 项目

  • 页面组件
    • 页面文件夹的直接子组件(如 src/views/about.vue
    • 嵌套文件夹中必须是 index.vue 才会被视为页面(如 src/views/a/b/index.vue
  • 普通组件:嵌套文件夹中非 index.vue 的文件(如 src/views/a/b.vue

React 项目

安装依赖

npm install react-router

配置 Vite

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import autoRouter from '@onoxm/vite-plugin-auto-router/react'

export default defineConfig({
  plugins: [
    react(),
    autoRouter({
      onGenerated: async filePaths => {
        for (const filePath of filePaths) {
          console.log('Generated:', filePath)
        }
      }
    })
  ]
})

目录结构

src/
├── pages/
│   ├── index.tsx
│   ├── __root__.tsx
│   ├── 404.tsx
│   └── user/
│       ├── index.tsx
│       ├── index.config.ts
│       ├── [id].tsx
│       └── [id].config.ts

特殊页面

  • home 页面:路径会自动转换为 /,作为首页路由
  • __root__ 页面:作为根路由容器,包裹所有其他路由
  • 404notfound 页面:路径会自动转换为 /*,作为 404 路由

页面配置

继承自 React Router RouteObject,并进行以下修改:

  • 移除: Component, element, children
  • 新增: type?: 'single' | 'wrap'
type: 'single'

type 配置为 single 时,该页面组件会作为独立路由生成:

// src/pages/user/index.config.ts
import { defineConfig } from '../../router/autoRouter'

export default defineConfig({
  type: 'single'
})

生成的路由结构:

// src/router/autoRouter.tsx
import type { RouteObject } from 'react-router'
import Pages404 from './../pages/404.tsx'
import Pages from './../pages/index.tsx'
import PagesRoot from './../pages/__root__.tsx'
import PagesUser from './../pages/user/index.tsx'
import PagesUserId from './../pages/user/[id]/index.tsx'

type PageConfig = Partial<
  Omit<RouteObject, 'Component' | 'element' | 'children'> & {
    type?: 'single' | 'wrap'
  }
>

export const defineConfig = (config: PageConfig) => config

export const routes: RouteObject[] = [
  {
    path: '/',
    element: <PagesRoot />,
    children: [
      {
        path: '/',
        element: <Pages />
      },
      {
        path: '/user',
        children: [
          {
            path: '',
            index: true,
            element: <PagesUser />
          },
          {
            path: ':id',
            children: [
              {
                path: '',
                index: true,
                action: async () => {},
                loader: async ({ params }) => await { params },
                element: <PagesUserId />
              }
            ]
          }
        ]
      }
    ]
  },
  {
    path: '/*',
    element: <Pages404 />
  }
]
type: 'wrap'

type 配置为 wrap 时,该页面组件会作为父路由容器包裹其下的子路由:

// src/pages/user/index.config.ts
import { defineConfig } from '../../router/autoRouter'

export default defineConfig({
  type: 'wrap'
})

生成的路由结构:

// src/router/autoRouter.tsx
import type { RouteObject } from 'react-router'
import Pages404 from './../pages/404.tsx'
import Pages from './../pages/index.tsx'
import PagesRoot from './../pages/__root__.tsx'
import PagesUser from './../pages/user/index.tsx'
import PagesUserId from './../pages/user/[id]/index.tsx'

type PageConfig = Partial<
  Omit<RouteObject, 'Component' | 'element' | 'children'> & {
    type?: 'single' | 'wrap'
  }
>

export const defineConfig = (config: PageConfig) => config

export const routes: RouteObject[] = [
  {
    path: '/',
    element: <PagesRoot />,
    children: [
      {
        path: '/',
        element: <Pages />
      },
      {
        path: '/user',
        element: <PagesUser />,
        children: [
          {
            path: ':id',
            children: [
              {
                path: '',
                index: true,
                action: async () => {},
                loader: async ({ params }) => await { params },
                element: <PagesUserId />
              }
            ]
          }
        ]
      }
    ]
  },
  {
    path: '/*',
    element: <Pages404 />
  }
]

Vue 项目

安装依赖

npm install vue-router

配置 Vite

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import autoRouter from '@onoxm/vite-plugin-auto-router/vue'

export default defineConfig({
  plugins: [
    vue(),
    autoRouter({
      pagesDir: './src/views',
      configPattern: '/**/*.meta.ts',
      onGenerated: async filePaths => {
        for (const filePath of filePaths) {
          console.log('Generated:', filePath)
        }
      }
    })
  ]
})

目录结构

src/
├── views/
│   ├── 404.vue
│   ├── home/
│   │   ├── index.vue
│   │   └── index.meta.ts
│   └── user/
│       ├── index.vue
│       ├── index.meta.ts
│       ├── [id].vue
│       └── [id].meta.ts

特殊页面

  • home 页面:路径会自动转换为 /,作为首页路由
  • __root__ 页面:作为根路由容器,包裹所有其他路由
  • 404notfound 页面:路径会自动转换为 /:pathMatch(.*)*,作为 404 路由

页面配置

继承自 Vue Router RouteRecordRaw,并进行以下修改:

  • 移除: component, children
  • 新增: type?: 'single' | 'wrap'
type: 'single'

type 配置为 single 时,该页面组件会作为独立路由生成:

// src/views/user/index.meta.ts
import { defineConfig } from '../../router/autoRouter'

export default defineConfig({
  type: 'single'
})

生成的路由结构:

// src/router/autoRouter.ts
import type { RouteRecordRaw } from 'vue-router'
import Views404 from './../views/404.vue'
import ViewsHome from './../views/home/index.vue'
import ViewsUser from './../views/user/index.vue'
import ViewsUserId from './../views/user/[id]/index.vue'

type PageConfig = Partial<
  Omit<RouteRecordRaw, 'component' | 'children'> & {
    type?: 'single' | 'wrap'
  }
>

export const defineConfig = (config: PageConfig) => config

export const routes: RouteRecordRaw[] = [
  {
    path: '/',
    children: [
      {
        path: '',
        name: 'home',
        component: ViewsHome
      }
    ]
  },
  {
    path: '/user',
    children: [
      {
        path: '',
        component: ViewsUser
      },
      {
        path: ':id',
        children: [
          {
            path: '',
            component: ViewsUserId
          }
        ]
      }
    ]
  },
  {
    path: '/:pathMatch(.*)*',
    children: [
      {
        path: '',
        component: Views404
      }
    ]
  }
]
type: 'wrap'

type 配置为 wrap 时,该页面组件会作为父路由容器包裹其下的子路由:

// src/views/user/index.meta.ts
import { defineConfig } from '../../router/autoRouter'

export default defineConfig({
  type: 'wrap'
})

生成的路由结构:

// src/router/autoRouter.ts
import type { RouteRecordRaw } from 'vue-router'
import Views404 from './../views/404.vue'
import ViewsHome from './../views/home/index.vue'
import ViewsUser from './../views/user/index.vue'
import ViewsUserId from './../views/user/[id]/index.vue'

type PageConfig = Partial<
  Omit<RouteRecordRaw, 'component' | 'children'> & {
    type?: 'single' | 'wrap'
  }
>

export const defineConfig = (config: PageConfig) => config

export const routes: RouteRecordRaw[] = [
  {
    path: '/',
    children: [
      {
        path: '',
        name: 'home',
        component: ViewsHome
      }
    ]
  },
  {
    path: '/user',
    component: ViewsUser,
    children: [
      {
        path: ':id',
        children: [
          {
            path: '',
            component: ViewsUserId
          }
        ]
      }
    ]
  },
  {
    path: '/:pathMatch(.*)*',
    children: [
      {
        path: '',
        component: Views404
      }
    ]
  }
]

⚙️ 配置选项

插件配置

| 选项 | 类型 | 默认值 | 说明 | | --------------- | ------------------------------------------------ | ---------------------- | ------------------------ | | framework | 'react' \| 'vue' | 'react' | 框架类型 | | pagesDir | string | './src/pages' | 页面目录 | | routesFile | string | undefined | 生成的路由文件路径 | | keepHome | boolean | false | 是否保留 home 页面 | | keepRoot | boolean | false | 是否保留 __root__ 页面 | | lazy | boolean | true | 是否启用懒加载 | | hmr | boolean | true | 是否启用热更新 | | configPattern | string | /**/*.config.{js,ts} | 配置文件模式 | | onGenerated | (filePaths: string[]) => Promise<void> \| void | undefined | 生成路由后调用的回调函数 |

页面配置

| 选项 | 类型 | 默认值 | 说明 | | ------ | -------------------- | ----------- | ----------------------------------------------------- | | type | 'single' \| 'wrap' | 'single' | 路由类型 | | path | string | undefined | 路由路径,支持使用 [currentPath] 占位符引用当前路径 | | * | any | any | 继承自路由配置 |

path 使用示例

使用 [currentPath] 占位符可以在替换路径时引用当前路径:

// src/pages/user/index.config.ts
import { defineConfig } from '../../router/autoRouter'

export default defineConfig({
  // 将 /user 替换为 /users/v2
  path: '/users/v2'
})

// 或者使用占位符,在当前路径后添加后缀
export default defineConfig({
  // 将 /user 替换为 /user/v2
  path: '[currentPath]/v2'
})

📄 License

MIT