You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js使用fs模块实现API路由子目录文件自动加载问题求助

实现方案

核心思路

你需要改造现有代码为递归遍历目录的逻辑,识别文件/文件夹,遇到文件夹就进入继续扫描,遇到.js后缀的路由文件再执行注册逻辑,即可支持任意层级的子目录嵌套。

完整实现代码

const { readdirSync, statSync } = require('fs');
const path = require('path');

module.exports = function(app){
    // 递归遍历目录的工具函数
    function scanDir(dirPath) {
        // 读取当前目录下所有内容
        const entries = readdirSync(dirPath);
        entries.forEach(entry => {
            const fullPath = path.join(dirPath, entry);
            const stat = statSync(fullPath);
            // 判断是文件夹的话继续递归扫描
            if (stat.isDirectory()) {
                scanDir(fullPath);
                return;
            }
            // 过滤非js文件、根目录的index.js
            if (entry === 'index.js' && dirPath === __dirname) return;
            if (!entry.endsWith('.js')) return;

            // 引入路由文件
            const route = require(fullPath);
            // 注册路由
            app.get(`/${route.name}`, async (req, res) => {
                route.run(req, res);
            });
        });
    }

    // 从当前routes目录开始扫描
    scanDir(__dirname);
}

可选优化:子目录名作为路由前缀

如果希望子目录下的路由自动带上目录名作为路径前缀,比如image routes下的路由自动匹配/image-routes/xxx格式的路径,可以增加相对路径计算逻辑,修改后代码如下:

const { readdirSync, statSync } = require('fs');
const path = require('path');

module.exports = function(app){
    function scanDir(dirPath) {
        const entries = readdirSync(dirPath);
        entries.forEach(entry => {
            const fullPath = path.join(dirPath, entry);
            const stat = statSync(fullPath);
            if (stat.isDirectory()) {
                scanDir(fullPath);
                return;
            }
            if (entry === 'index.js' && dirPath === __dirname) return;
            if (!entry.endsWith('.js')) return;

            // 计算当前文件相对于routes根目录的路径
            const relativePath = path.relative(__dirname, fullPath);
            // 拆分路径提取目录名作为前缀,自动替换目录名中的空格为短横线
            const pathSegments = relativePath.split(path.sep).filter(seg => seg !== path.basename(relativePath));
            const prefix = pathSegments.map(seg => seg.replace(/\s+/g, '-').toLowerCase()).join('/');

            const route = require(fullPath);
            // 拼接前缀到路由路径上
            const routePath = prefix ? `/${prefix}/${route.name}` : `/${route.name}`;
            app.get(routePath, async (req, res) => {
                route.run(req, res);
            });
        });
    }
    scanDir(__dirname);
}

注意事项

  • 代码默认支持任意层级的子目录嵌套,不止二级目录
  • 带空格的目录名处理规则可根据自己的命名规范自行调整
  • 如果需要支持POST、PUT等其他请求方法,可在路由导出对象中增加method字段做动态判断

内容的提问来源于stack exchange,提问作者TagliatelleLmao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:24:01