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

JavaScript中是否存在与模块系统无关的当前文件路径获取方法?

兼容CommonJS与ESM的当前文件路径获取方案

问题背景

在Node.js的CommonJS模块中,__dirname和__filename是实用的魔术变量,但ES模块中需要手动重构:

import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

但库开发场景下,代码通常会编译为CommonJS和ESM两种格式,直接用条件判断的写法会导致非ESM环境解析import语句时报错,甚至用eval绕过import.meta.url的尝试也无法生效(测试环境:Node 18 LTS,20.x、21.x版本存在相同问题)。需要一种与模块系统无关的兼容方案。

可行解决方案

方案1:同步兼容方案(推荐)

利用Node.js 18+允许ESM环境中使用require的特性,结合环境判断实现同步获取:

let __filename: string;
let __dirname: string;

// 检测CommonJS环境
if (typeof module !== 'undefined' && module.exports) {
  const path = require('node:path');
  __filename = module.filename;
  __dirname = path.dirname(__filename);
} else {
  // ESM环境同步导入依赖
  const { fileURLToPath } = require('node:url');
  const { dirname } = require('node:path');
  __filename = fileURLToPath(import.meta.url);
  __dirname = dirname(__filename);
}

export { __filename, __dirname };

核心逻辑:

  • CommonJS环境直接复用module.filename和path.dirname
  • ESM环境通过require同步导入工具函数,避免顶层import触发CommonJS环境语法错误

方案2:异步兼容方案

如果需要避免在ESM中使用require,可以用动态导入实现异步获取:

async function getCurrentFilepath(): Promise<string> {
  if (typeof __filename !== 'undefined') {
    return __filename;
  }
  const { fileURLToPath } = await import('node:url');
  return fileURLToPath(import.meta.url);
}

async function getCurrentDirname(): Promise<string> {
  if (typeof __dirname !== 'undefined') {
    return __dirname;
  }
  const { fileURLToPath } = await import('node:url');
  const { dirname } = await import('node:path');
  return dirname(fileURLToPath(import.meta.url));
}

注意:此方案返回Promise,需要调用方处理异步逻辑。

方案3:调用栈解析(备选,不推荐)

通过Error调用栈提取文件路径,依赖栈结构稳定性,仅作为 fallback 方案:

function getCurrentFilepath(): string {
  const err = new Error();
  const stackLine = err.stack?.split('\n')[1];
  if (!stackLine) throw new Error('无法解析调用栈');
  
  const pathMatch = stackLine.match(/\((.*?)\)/);
  if (!pathMatch) throw new Error('无法提取文件路径');
  
  return pathMatch[1];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:43:10