【nodejs】“__dirname is not defined”错误修复

▒ 目录 ▒

    • [🛫 问题](#🛫 问题)
    • [1️⃣ 原理](#1️⃣ 原理)
    • [2️⃣ 禁用 ESM 模式并改用 CommonJS](#2️⃣ 禁用 ESM 模式并改用 CommonJS)
    • [3️⃣ 在 ESM 模式下自实现__dirname](#3️⃣ 在 ESM 模式下自实现__dirname)
    • [📖 参考资料](#📖 参考资料)

🛫 问题

描述

从网上找了一份代码,其中包含了__dirname变量的使用,结果运行的时候报错:__dirname is not defined

环境

版本号 描述
文章日期 2023-06-
操作系统 Ubuntu 20.04.4 LTS CSDN开发云
node -v v16.17.0 npm -v (8.15.0)
Cloud IDE 1.71.0
操作系统 Win11 - 21H2 - 22000.1335
Python 3.7.1
frida.exe 15.0.18

1️⃣ 原理

CommonJS vs ESM

讨论__dirname报错,首先要分清楚CommonJS 和 ESM的区别。

CommonJS 和 ESM(ECMAScript Modules) 都是 JavaScript 模块系统的规范,用于组织和管理代码。它们之间有一些区别,下面简要介绍一下:

特点 CommonJS ESM
加载方式 同步加载 异步加载
导出/引入关键字 module.exports 和 require() export 和 import
支持环境 Node.js 默认支持 现代浏览器和最新版本的 Node.js 支持
应用范围 主要用于服务器端开发,如 Node.js 在浏览器端和 Node.js 中有广泛应用,是未来趋势

错误原因

在 CommonJS 模式下,__dirname 是包含当前文件目录变量。 许多Node.js项目都依赖于此变量。

但不能在 ESM 模式下使用(ESM模式不提供 __dirname 变量)。 您有两种选择:

  • 禁用 ESM 模式并改用 CommonJS
  • 聚填充__dirname

2️⃣ 禁用 ESM 模式并改用 CommonJS

在 JavaScript 中,通常文件扩展名 ".js" 用于表示普通的 JavaScript 文件,

而 ".mjs" 用于表示 ECMAScript 模块(ESM)文件。这两种文件扩展名的区别在于它们所代表的 JavaScript 模块类型。

  • .js 文件:通常用来表示普通的 JavaScript 文件,其中可能包含常规的 JavaScript 代码,采用 CommonJS 或其他模块加载方案。
  • .mjs 文件:表示 ECMAScript 模块,这种文件中的代码采用了 ECMAScript Modules(ESM)规范,即使用 "import" 和 "export" 关键字来定义模块。

要使用 ".mjs" 文件,您需要确保在 Node.js 中启用了对 ECMAScript 模块的支持。您可以通过以下几种方式之一实现:

方案一:项目

Node.js 项目中的 package.json 文件是一个用于描述项目信息、依赖关系和脚本命令的 JSON 文件。它位于项目根目录下,是 Node.js 项目的重要配置文件之一。

在 Node.js 项目中的 package.json 文件中,"type" 字段不要设置为 "module",以明确告知 Node.js 不使用 ESM 规范(或者直接删除)

方案二:单文件

对于单文件运行node,即不包含 package.json 文件的情况。node是根据文件后缀判断运行模式的。

我们确保文件后缀是.js,而不是.mjs即可使用__dirname。

3️⃣ 在 ESM 模式下自实现__dirname

在 ECMAScript 模块(ESM)中,与 CommonJS 不同,没有像 __dirname 这样的内置变量来表示当前模块的目录路径。不过,您可以通过一些方法来模拟实现类似的功能。
一种常见的方法是使用 import.meta.url 属性来获取当前模块的 URL,然后从中提取出目录路径。下面是一个示例代码,演示如何在 ESM 模式下自实现类似 __dirname 的功能:

js 复制代码
import path from 'path';
import { fileURLToPath } from 'url';

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

在这个示例中,我们首先导入了 Node.js 中的 fileURLToPath 和 dirname 函数,然后使用 import.meta.url 获取当前模块的 URL。接着,通过 fileURLToPath 将 URL 转换为文件路径,并最终通过 dirname 获取该文件路径的目录部分,从而模拟实现了类似 __dirname 的功能。

请注意,这种方法依赖于 Node.js 提供的 url 和 path 模块,确保您的项目中已安装这些模块。这样,您就可以在 ESM 模式下获取当前模块的目录路径,类似于 CommonJS 中的 __dirname 变量。

📖 参考资料

相关推荐
Z3r4y1 天前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
itas1094 天前
Electron获取nodejs和chrome版本信息
javascript·chrome·electron·nodejs·node
henan程序媛7 天前
jenkins部署Maven和NodeJS项目
运维·jenkins·maven·nodejs
MavenTalk7 天前
2024前端技术发展概况
前端·vue·nodejs·react·angular·大前端
秦伟杰13 天前
mac M1,M2,M3芯片踩坑 nodejs ruby brew
arm·nodejs·ruby·mac·nvm·m2·brew·m1·rvm·m3·苹果芯片
程序者王大川24 天前
【移动端】Flutter与uni-app:全方位对比分析
flutter·uni-app·app·nodejs·全栈·dart·移动端
香吧香1 个月前
安装nvm,并通过nvm安装nodejs
nodejs
营赢盈英2 个月前
Can‘t use openai in command prompt
javascript·prompt·nodejs·reactjs·openai api·command-line
stonefisher2 个月前
推荐Nodejs下高效存储树到数据库工具库-FlexTree
javascript·数据库·nodejs·tree·prisma
loong_XL2 个月前
vue、react前端框架实现TodoList页面案例
前端·vue·nodejs·react