We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ECMAScript 模块是 JavaScript 的新标准格式。在 Node.js 中越来越多的库逐渐从从 CommonJS 转移到 ES 模块
注:这里是指“真”ES 模块并不是指代码中 Node.js 中使用 import 写法但是实际被 tsc 转成 commonJS 的形式
但是 Node.js ES 开发中此前有一个棘手的问题是获取当前文件目录、路径。不过这个问题在最近也已经解决
在 ES 模块中,现在可以使用以下方式而不是使用__dirname或__filename
__dirname
__filename
import.meta.dirname // 当前模块的目录名 (__dirname) import.meta.filename //当前模块文件名 (__filename)
通过访问当前模块的目录路径,可以相对于代码所在位置遍历文件系统并在项目中读取或写入文件,或动态导入代码。相关的使用方式随着时间的推移而发生了一些变化,从 CommonJS 的实现到最新的 ES 模块更新
Node.js 最初使用 CommonJS 模块系统。CommonJS 提供了两个变量,返回当前模块的目录名称和文件名称,分别是__dirname和__filename
__dirname // 当前模块所在的目录 __filename // 当前模块文件名
__dirname和__filename在 ES 模块中不可用。需要使用以下代码来实现获取
import * as url from 'url'; const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); const __filename = url.fileURLToPath(import.meta.url);
最终在经过许多讨论后,现在有了更好的方法。自从Node.js20.11.0和Deno 1.40.0和Bun 1.0.23之后可以调用import.meta对象的dirname和filename属性来获取了
import.meta
dirname
filename
import.meta.dirname // 当前模块所在的目录 import.meta.filename// 当前模块文件名
ES 模块是 JavaScript 的标准。然而 JavaScript 最初是作为在 Web 浏览器中运行的语言而诞生的。Node.js 流行起来后开始在服务器上运行 JavaScript,但必须使用一些约定来加载模块,Node.js 项目早期做出的一个选择是采用 CommonJS 模块系统及其相关内容
ES 模块是为浏览器和服务器环境设计的。浏览器通常没有文件系统访问权限,因此提供对当前目录或文件名的访问是没有意义。然而对于浏览器处理 URL,可以使用file://scheme以 URL 格式提供文件路径。因此,ES 模块具有对模块的 URL 的引用。即import.meta.url。可以看看在 Node.js 中可以使用 URL 的相关使用
file://scheme
import.meta.ur
假设一个名为module.js的 ES 模块包含以下代码:
为module.js
console.log(import.meta.url);
如果使用 Node.js 的服务器上运行此文件,则会得到以下结果:
$ node module.js file:///path/to/module.js
如果 Web 浏览器中加载 module.js,则会得到以下结果:
https://example.com/module.js
基于不同上下文会有不同的结果
import.meta.url是一个描述 URL 的字符串,而不是一个 URL 对象。可以通过将该字符串传递给URL构造函数将其转换为真正的 URL 对象:
import.meta.url
URL
const fileUrl = new URL(import.meta.url); console.log(url.protocol); // Node.js: "file:" // Browser: "https:"
使用 URL 对象,可以使用 Node.js 的 URL 模块将模块的 URL 转换为文件路径,等价于 __filename
import * as url from "url"; const fileUrl = new URL(import.meta.url); const filePath = url.fileURLToPath(fileUrl); console.log(filePath); // /path/to/module.js
也可以操作 URL 来获取目录名,等价于__dirname
import * as url from "url"; const directoryUrl = new URL(".", import.meta.url); const directoryPath = url.fileURLToPath(directoryUrl); console.log(directoryPath); // /path/to
大多数的代码可能都是需要使用路径字符串来在 Node.js 中执行常见的文件操作。但其实许多在字符串路径上工作的 Node.js API 也可以使用URL对象
__dirname 最常见的用途是遍历目录以查找要加载的数据文件。例如,如果 module.js 文件与名为 data.json 的文件位于同一目录中,并且想将数据加载到脚本中,则以前会像这样使用 __dirname
module.js
data.json
const { join } = require("node:path"); const { readFile } = require("node:fs/promises"); function readData() { const filePath = join(__dirname, "data.json"); return readFile(filePath, { encoding: "utf8" }); } }
在 ES 模块中可以直接使用import.meta.dirname
import.meta.dirname
import { join } from "node:path"; import { readFile } from "node:fs/promises"; function readData() { const filePath = join(import.meta.dirname, "data.json"); return readFile(filePath, { encoding: "utf8" }); }
但是也可以像如下使用 URL 对象:
import { readFile } from "node:fs/promises"; function readData() { const fileUrl = new URL("data.json", import.meta.url); return readFile(fileUrl, { encoding: "utf8" }); }
由于 ES 模块为客户端和服务器编写的 JavaScript 带来了一致性,因此使用 URL 对象而不是路径字符串也可以实现相同的效果。更多关于替代__dirname可以参考
import.meta.dirname和import.meta.filename可以在最新版本的 Node.js、Deno 和 Bun 中使用
import.meta.filename
Bun 已经提前实现了import.meta.dir和import.meta.pat,它们是等效的,所以dirname和filename在 bun 其实是dir和path的别名
import.meta.dir
import.meta.pat
dir
path
由于这个属性仅涉及基础文件系统,因此仅在import.meta.url的 scheme 为file:时可用。也就是说在浏览器环境中不可用;在浏览器中尝试使用import.meta.dirname将仅返回 undefined
file:
undefined
__dirname is back in Node.js with ES modules
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
ECMAScript 模块是 JavaScript 的新标准格式。在 Node.js 中越来越多的库逐渐从从 CommonJS 转移到 ES 模块
但是 Node.js ES 开发中此前有一个棘手的问题是获取当前文件目录、路径。不过这个问题在最近也已经解决
结论
在 ES 模块中,现在可以使用以下方式而不是使用
__dirname
或__filename
获取当前目录
通过访问当前模块的目录路径,可以相对于代码所在位置遍历文件系统并在项目中读取或写入文件,或动态导入代码。相关的使用方式随着时间的推移而发生了一些变化,从 CommonJS 的实现到最新的 ES 模块更新
旧的 CommonJS 方式
Node.js 最初使用 CommonJS 模块系统。CommonJS 提供了两个变量,返回当前模块的目录名称和文件名称,分别是
__dirname
和__filename
旧的 ES 模块方式
__dirname
和__filename
在 ES 模块中不可用。需要使用以下代码来实现获取最新的 ES 模块方式
最终在经过许多讨论后,现在有了更好的方法。自从Node.js20.11.0和Deno 1.40.0和Bun 1.0.23之后可以调用
import.meta
对象的dirname
和filename
属性来获取了为什么需要一个新的 API
ES 模块是 JavaScript 的标准。然而 JavaScript 最初是作为在 Web 浏览器中运行的语言而诞生的。Node.js 流行起来后开始在服务器上运行 JavaScript,但必须使用一些约定来加载模块,Node.js 项目早期做出的一个选择是采用 CommonJS 模块系统及其相关内容
ES 模块是为浏览器和服务器环境设计的。浏览器通常没有文件系统访问权限,因此提供对当前目录或文件名的访问是没有意义。然而对于浏览器处理 URL,可以使用
file://scheme
以 URL 格式提供文件路径。因此,ES 模块具有对模块的 URL 的引用。即import.meta.ur
l。可以看看在 Node.js 中可以使用 URL 的相关使用假设一个名
为module.js
的 ES 模块包含以下代码:如果使用 Node.js 的服务器上运行此文件,则会得到以下结果:
如果 Web 浏览器中加载 module.js,则会得到以下结果:
基于不同上下文会有不同的结果
import.meta.url
是一个描述 URL 的字符串,而不是一个 URL 对象。可以通过将该字符串传递给URL
构造函数将其转换为真正的 URL 对象:使用 URL 对象,可以使用 Node.js 的 URL 模块将模块的 URL 转换为文件路径,等价于
__filename
也可以操作 URL 来获取目录名,等价于
__dirname
使用 URL 而不是字符串
大多数的代码可能都是需要使用路径字符串来在 Node.js 中执行常见的文件操作。但其实许多在字符串路径上工作的 Node.js API 也可以使用
URL
对象__dirname
最常见的用途是遍历目录以查找要加载的数据文件。例如,如果module.js
文件与名为data.json
的文件位于同一目录中,并且想将数据加载到脚本中,则以前会像这样使用__dirname
在 ES 模块中可以直接使用
import.meta.dirname
但是也可以像如下使用 URL 对象:
由于 ES 模块为客户端和服务器编写的 JavaScript 带来了一致性,因此使用 URL 对象而不是路径字符串也可以实现相同的效果。更多关于替代
__dirname
可以参考如何找到
import.meta.dirname
import.meta.dirname
和import.meta.filename
可以在最新版本的 Node.js、Deno 和 Bun 中使用Bun 已经提前实现了
import.meta.dir
和import.meta.pat
,它们是等效的,所以dirname
和filename
在 bun 其实是dir
和path
的别名由于这个属性仅涉及基础文件系统,因此仅在
import.meta.url
的 scheme 为file:
时可用。也就是说在浏览器环境中不可用;在浏览器中尝试使用import.meta.dirname
将仅返回undefined
参考
__dirname is back in Node.js with ES modules
The text was updated successfully, but these errors were encountered: