__dirname 在ES模块中的使用

前言

ECMAScript模块是 JavaScript 的新标准格式。在Node.js中越来越多的库逐渐从从CommonJS转移到ES模块

注:这里是指“真”ES 模块并不是指代码中 Node.js 中使用 import 写法但是实际被 tsc 转成 commonJS 的形式

但是Node.js ES 开发中此前有一个棘手的问题是获取当前文件目录、路径。不过这个问题在最近也已经解决

结论

在ES模块中,现在可以使用以下方式而不是使用__dirname__filename

import.meta.dirname  // 当前模块的目录名 (__dirname)
import.meta.filename //当前模块文件名 (__filename)

获取当前目录

通过访问当前模块的目录路径,可以相对于代码所在位置遍历文件系统并在项目中读取或写入文件,或动态导入代码。相关的使用方式随着时间的推移而发生了一些变化,从CommonJS的实现到最新的ES模块更新

旧的CommonJS方式

Node.js最初使用CommonJS模块系统。CommonJS提供了两个变量,返回当前模块的目录名称和文件名称,分别是__dirname__filename

__dirname  // 当前模块所在的目录
__filename // 当前模块文件名

旧的 ES 模块方式

__dirname__filename在ES模块中不可用。需要使用以下代码来实现获取

import * as url from 'url';

const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const __filename = url.fileURLToPath(import.meta.url);

最新的 ES 模块方式

最终在经过许多讨论后,现在有了更好的方法。自从Node.js20.11.0和Deno 1.40.0和Bun 1.0.23之后可以调用import.meta对象的dirnamefilename属性来获取了

import.meta.dirname // 当前模块所在的目录
import.meta.filename// 当前模块文件名

为什么需要一个新的 API

ES模块是JavaScript的标准。然而JavaScript最初是作为在Web浏览器中运行的语言而诞生的。Node.js流行起来后开始在服务器上运行JavaScript,但必须使用一些约定来加载模块,Node.js项目早期做出的一个选择是采用CommonJS模块系统及其相关内容

ES模块是为浏览器和服务器环境设计的。浏览器通常没有文件系统访问权限,因此提供对当前目录或文件名的访问是没有意义。然而对于浏览器处理URL,可以使用file://scheme以URL格式提供文件路径。因此,ES模块具有对模块的URL的引用。即import.meta.url。可以看看在Node.js中可以使用URL的相关使用

假设一个名为module.js的ES模块包含以下代码:

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对象:

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

使用 URL 而不是字符串

大多数的代码可能都是需要使用路径字符串来在Node.js中执行常见的文件操作。但其实许多在字符串路径上工作的Node.js API也可以使用URL对象

__dirname 最常见的用途是遍历目录以查找要加载的数据文件。例如,如果 module.js 文件与名为 data.json 的文件位于同一目录中,并且想将数据加载到脚本中,则以前会像这样使用 __dirname

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 { 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.dirnameimport.meta.filename可以在最新版本的Node.js、Deno和Bun中使用

Bun已经提前实现了import.meta.dirimport.meta.pat,它们是等效的,所以dirnamefilename在 bun 其实是dirpath的别名

由于这个属性仅涉及基础文件系统,因此仅在import.meta.url的 scheme为file:时可用。也就是说在浏览器环境中不可用;在浏览器中尝试使用import.meta.dirname将仅返回 undefined

参考

__dirname is back in Node.js with ES modules

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/523414.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java-字符知识扩展

前言:了解字符有关的知识将会对你后面的学习和掌握有关知识有更多的帮助 1.字符的强制转换 所以字符本质还是数字 2.转义字符: 3.布尔值扩展 搬砖好累呜呜呜

请你先搞清楚什么是it行业!

IT,即信息技术,掌握了它就等于拥有了通向未来的钥匙🗝️。现在,就来看看怎样从0基础起步,成为IT圈的一员吧! 第一步:认识it IT"代表信息技术(Information Technology&#xf…

[羊城杯 2020]Easyphp2 ---不会编程的崽

摆烂一周了,继续更!!题目还是简单哦。 提示明显要我们修改数据包,第一反应是修改referer。试了一下不太对。url很可能存在文件包含 使用伪协议读取一下源码吧。它过滤了base64关键字。尝试url编码绕过,这里可以使用二…

搜索与图论——拓扑排序

有向图的拓扑排序就是图的宽度优先遍历的一个应用 有向无环图一定存在拓扑序列(有向无环图又被称为拓扑图),有向有环图一定不存在拓扑序列。无向图没有拓扑序列。 拓扑序列:将一个图排成拓扑序后,所有的边都是从前指…

【算法篇】三道题理解算法思想——认识BFS

BFS(宽搜) 宽度优先遍历和深度优先遍历组成了大家熟悉的搜索算法,这两种算法也是蓝桥杯之类竞赛题的常考思想,正巧马上蓝桥杯临近,博主也是刷了很多BFS相关的题型,在这篇文章中会从力扣上选取三道简单的宽搜…

vue2 列表一般不使用索引删除的原因

在 Vue 中使用索引来删除列表项可能会导致一系列问题,尤其是在处理动态列表时。以下是一些可能的问题和相应的例子: 1. 数据不一致问题 当你使用索引来删除列表中的某个项时,如果列表中的其他项发生了变化(比如新增或重新排序&a…

全网短剧搜索前端源码开源分享可改自己的接口

全网短剧搜索前端源码 内含7000短剧资源(不支持在线播放) 源码全开源,可以修改成自己的接口 178、226、347行修改 源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

全国月度平均风速空间分布数据/月度降雨量分布/月均气温分布

引言 风速是指空气相对于地球某一固定地点的运动速率。一般来讲,风速越大,风力等级越高,风的破坏性越大。平均风速,一定时段内,数次观测的风速的平均值。一般表达方式为[m/s]。 正文 我国位于欧亚大陆东部、太平洋西岸…

YOLO算法改进Backbone系列之:PVT

摘要:尽管基于CNNs的backbone在多种视觉任务中取得重大进展,但本文提出了一个用于密集预测任务的、无CNN的的简单backbone——Pyramid Vision Transformer(PVT)。相比于ViT专门用于图像分类的设计,PVT将金字塔结构引入…

第7章.自我一致性提示

自我一致性提示技术,它通过确保ChatGPT的输出与输入的精准匹配, 提高了对话的连贯性和准确性,为用户带来了更加智能和满意的交互体验。 它广泛适用于事实核查、数据验证和内容一致性检查等多样化场景。 您需在输入前添加如:“生…

【Entity Framework】EF配置文件设置详解

【Entity Framework】EF配置文件设置详解 文章目录 【Entity Framework】EF配置文件设置详解一、概述二、实体框架配置部分三、连接字符串四、EF数据库提供程序五、EF侦听器六、将数据库操作记录到文件中七、Code First默认连接工厂八、数据库初始值设定项 一、概述 EF实体框架…

不开玩笑,你应该像「搬砖」一样写代码!斯坦福大学研究如是说

由于程序员不可避免要进行很多重复性的工作,并且工作强度很高,导致有一种自嘲的说法出现:程序员们自称自己每天都在搬砖(实际上很多职场人都这么自嘲)。我相信当我们说工作像「搬砖」的时候,只是在表达一种…

隐私保护和带宽有效的联邦学习:在医院死亡率预测中的应用-文章翻译

隐私保护和带宽有效的联邦学习:在医院死亡率预测中的应用 摘要 机器学习,特别是联邦机器学习,在医学研究和患者护理方面开辟了新的视角。尽管联邦机器学习在隐私方面比集中式机器学习有所改进,但它不提供可证明的隐私保证。此外,联邦机器学习在带宽消耗方面相当昂贵,因…

对模型用check_urdf后缀为.urdf时显示的错误,如何解决?

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

python买铅笔 2024年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析

目录 python买铅笔 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python买铅笔 2024年3月 python编程等级考试级编程题 一、题目要求 1、编…

Redis 应用问题解决——缓存穿透、缓存击穿、缓存雪崩、分布式锁

缓存穿透 key对应的数据在数据源不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能…

【精品整理】最新数据安全评估标准合集

最新数据安全评估标准合集,以下是资料的目录,共12份。如需下载,请前往星球查阅和获取:https://t.zsxq.com/18JrHhWtQ 1、网络安全标准实践指南 2、数据安全风险评估方法 3、个人信息安全影响评估指南 4、数据出境安全评估指南 5、…

计算机视觉入门:开启图像理解之旅

🧑 作者简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

物联网实战--驱动篇之(三)LoRa(sx1278)

目录 一、LoRa简介 二、sx1278模块 三、硬件抽象层 四、SX1278初始化 五、发送时间计算 六、发送模式 七、接收模式 八、总结 一、LoRa简介 LoRa在物联网传输领域有着举足轻重的地位,平时大家可能比较少听说,因为它主要还是在行业应用&#xff0…

Python第四次作业

周六: 1. 找出10000以内能被5或6整除,但不能被两者同时整除的数(函数) def find_number():for number in range(0,10000):if number % 5 0 or number % 6 0:if number % 5 ! number % 6:ls.append(number)print(ls)ls [] fin…