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

Node.js中如何通过模块名/目录字符串自动导入导出模块?

自动导入并导出目录下的模块

我的文件夹结构如下:

modules
    module-and
        index.js
    module-not
        index.js
    module-or
        index.js
    module-xor
        index.js
    moduleBundler.js

我正在编写moduleBundler.js,希望自动从各个模块文件夹导入模块并统一导出,而非像下面这样硬编码:

import ModuleAnd from "./module-and";
import ModuleNot from "./module-not";
import ModuleOr from "./module-or";
import ModuleXor from "./module-xor";
export { ModuleAnd, ModuleNot, ModuleOr, ModuleXor };

我已经通过以下代码获取到所有模块的目录和对应导出名称:

const moduleDirectories = getDirectories(__dirname);
const moduleNames = moduleDirectories.map(x => x.slice(0, 1).toUpperCase() + camelise(x).slice(1));

console.log(moduleDirectories);
>>> [ 'module-and', 'module-not', 'module-or', 'module-xor' ]

console.log(moduleNames);
>>> [ 'ModuleAnd', 'ModuleNot', 'ModuleOr', 'ModuleXor' ]

但尝试动态导入时遇到了问题:

  1. 循环直接导入报错:
for (const i in moduleNames) {
    import moduleNames[i] from ("./" + moduleDirectories[i]);
}

报错:ReferenceError: from is not defined

  1. 用eval()测试也失败:
for (const [key, value] of Object.entries(moduleNames)) {
    const directory = "./" + moduleDirectories[parseInt(key)];
    eval(`import ${value} from "${directory}"`);
}

报错:SyntaxError: Cannot use import statement outside a module

我不想在package.json里加"type": "module",也希望完全避免用eval()。请问该如何实现动态导入并统一导出这些模块?


解决方案(CommonJS环境)

既然你不想启用ES模块模式,直接用CommonJS的require()就能实现动态导入,再构建导出对象即可:

const fs = require('fs');
const path = require('path');

// 实现getDirectories函数(如果还没写)
function getDirectories(dir) {
    return fs.readdirSync(dir, { withFileTypes: true })
        .filter(dirent => dirent.isDirectory())
        .map(dirent => dirent.name);
}

// 实现camelise函数(如果还没写)
function camelise(str) {
    return str.replace(/-([a-z])/g, (match, char) => char.toUpperCase());
}

const moduleDirectories = getDirectories(__dirname);
const moduleNames = moduleDirectories.map(x => x.slice(0, 1).toUpperCase() + camelise(x).slice(1));

// 构建导出对象
const exportsObj = {};
moduleDirectories.forEach((dir, index) => {
    const modulePath = path.join(__dirname, dir);
    // 导入模块的默认导出
    const moduleDefault = require(modulePath).default;
    exportsObj[moduleNames[index]] = moduleDefault;
});

// 导出所有模块
module.exports = exportsObj;

之后其他文件就能通过const { ModuleAnd, ModuleNot } = require('./moduleBundler')来按需导入模块。

补充:如果后续考虑ES模块模式

如果之后愿意启用ES模块(在package.json中添加"type": "module"),可以用动态import()函数实现,完全不需要eval():

import fs from 'fs/promises';
import path from 'path';

// 实现camelise函数
function camelise(str) {
    return str.replace(/-([a-z])/g, (match, char) => char.toUpperCase());
}

async function getModules() {
    const moduleDirectories = await fs.readdir(__dirname, { withFileTypes: true })
        .then(dirents => dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name));
    
    const moduleNames = moduleDirectories.map(x => x.slice(0, 1).toUpperCase() + camelise(x).slice(1));
    
    const exportsObj = {};
    for (let i = 0; i < moduleDirectories.length; i++) {
        const modulePath = `./${moduleDirectories[i]}`;
        const module = await import(modulePath);
        exportsObj[moduleNames[i]] = module.default;
    }
    return exportsObj;
}

// 导出包含所有模块的对象(需异步导入)
export default await getModules();

这种方式下,导入该bundler的地方需要用import bundler from './moduleBundler',且因为是异步操作,可能需要在异步函数中使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:35:40