webpack-routes-plugin
Version:
基于文件系统的webpack约定式路由插件 - 自动生成路由配置,告别手写路由文件
99 lines (83 loc) • 3.13 kB
JavaScript
const path = require('path');
const fs = require('fs');
const RouteGenerator = require('./RouteGenerator');
class WebpackRoutesPlugin {
constructor(options = {}) {
this.options = {
// 页面文件目录,默认为 pages
pagesDir: options.pagesDir || 'src/pages',
// 生成的路由文件路径
outputPath: options.outputPath || 'src/routes.js',
// 文件扩展名
extensions: options.extensions || ['.js', '.jsx', '.ts', '.tsx'],
// 是否包含子目录
includeSubdirectories: options.includeSubdirectories !== false,
// 排除的文件或目录
exclude: options.exclude || [],
// 自定义路由配置
customRoutes: options.customRoutes || [],
// 是否生成TypeScript类型定义
generateTypes: options.generateTypes || false,
...options
};
this.routeGenerator = new RouteGenerator(this.options);
}
apply(compiler) {
const pluginName = 'WebpackRoutesPlugin';
// 在编译开始前生成路由
compiler.hooks.beforeRun.tapAsync(pluginName, (compilation, callback) => {
this.generateRoutes(callback);
});
// 在监听模式下,每次重新编译时生成路由
compiler.hooks.watchRun.tapAsync(pluginName, (compilation, callback) => {
this.generateRoutes(callback);
});
// 监听页面文件变化
if (compiler.options.mode === 'development') {
compiler.hooks.afterCompile.tap(pluginName, (compilation) => {
const pagesDir = path.resolve(compiler.context, this.options.pagesDir);
this.addDirectoryDependency(compilation, pagesDir);
});
}
}
generateRoutes(callback) {
try {
console.log('🚀 正在生成约定式路由...');
const routes = this.routeGenerator.generateRoutes();
const outputPath = path.resolve(process.cwd(), this.options.outputPath);
// 确保输出目录存在
const outputDir = path.dirname(outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// 写入路由文件
fs.writeFileSync(outputPath, routes);
console.log(`✅ 路由文件已生成: ${outputPath}`);
if (callback) callback();
} catch (error) {
console.error('❌ 生成路由时发生错误:', error);
if (callback) callback(error);
}
}
addDirectoryDependency(compilation, directory) {
if (fs.existsSync(directory)) {
compilation.fileDependencies.add(directory);
// 递归添加子目录依赖
const addSubdirectories = (dir) => {
const items = fs.readdirSync(dir);
items.forEach(item => {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
compilation.fileDependencies.add(fullPath);
addSubdirectories(fullPath);
} else {
compilation.fileDependencies.add(fullPath);
}
});
};
addSubdirectories(directory);
}
}
}
module.exports = WebpackRoutesPlugin;