自定义Vite插件开发实战

226 阅读1分钟

自定义Vite插件开发实战

1. 插件功能定义

  • 场景:解决团队重复性工作
  • 插件功能:自动生成路由配置(基于文件系统)
  • 输入src/pages目录下的.vue文件
  • 输出src/router/routes.ts动态路由配置

2. 插件完整代码

// vite-plugins/auto-routes.ts
import { Plugin } from 'vite';
import fs from 'fs/promises';
import path from 'path';

interface RouteMeta {
  path: string;
  component: string;
  children?: RouteMeta[];
}

export default function autoRoutes(): Plugin {
  return {
    name: 'vite-plugin-auto-routes',
    // 在构建启动时执行
    async buildStart() {
      const pagesDir = path.join(process.cwd(), 'src/pages');
      const outputFile = path.join(process.cwd(), 'src/router/routes.ts');
      
      // 递归读取pages目录
      const generateRoutes = async (dir: string, basePath = ''): Promise<RouteMeta[]> => {
        const entries = await fs.readdir(dir, { withFileTypes: true });
        const routes: RouteMeta[] = [];
        
        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);
          if (entry.isDirectory()) {
            // 处理子目录
            routes.push({
              path: `/${basePath}${entry.name}`,
              children: await generateRoutes(fullPath, `${basePath}${entry.name}/`)
            });
          } else if (entry.name.endsWith('.vue')) {
            // 处理vue文件
            const name = entry.name.replace('.vue', '');
            routes.push({
              path: `/${basePath}${name === 'index' ? '' : name}`,
              component: `() => import('../pages/${basePath}${entry.name}')`
            });
          }
        }
        return routes;
      };

      const routes = await generateRoutes(pagesDir);
      const code = `// Auto-generated by vite-plugin-auto-routes\nexport default ${JSON.stringify(routes, null, 2)}`;
      
      // 写入路由文件
      await fs.writeFile(outputFile, code, 'utf-8');
      console.log('🚀 Routes generated successfully!');
    }
  };
}

3. 集成到Vite项目

// vite.config.ts
import autoRoutes from './vite-plugins/auto-routes';

export default defineConfig({
  plugins: [
    vue(), 
    autoRoutes() // 启用插件
  ]
});

4. 效果演示

  • 目录结构

    src/
      pages/
        home/
          index.vue
        about.vue
      router/
        routes.ts (自动生成)
    
  • 生成内容

    // routes.ts
    export default [
      {
        path: "/home",
        component: () => import('../pages/home/index.vue')
      },
      {
        path: "/about",
        component: () => import('../pages/about.vue')
      }
    ]
    

5. 插件进阶能力

  1. 热更新支持

    // 在插件中添加
    configureServer(server) {
      server.watcher.on('change', async (file) => {
        if (file.includes('src/pages')) {
          await this.buildStart();
          server.ws.send({ type: 'full-reload' });
        }
      });
    }
    
  2. 类型安全
    生成.d.ts文件补充路由类型定义。

  3. 配置化
    允许通过参数自定义扫描目录和输出位置:

    interface Options {
      pagesDir?: string;
      outputFile?: string;
    }