Node.js模块发布前测试 存在data目录却报ENOENT scandir './data'错误的修复方法
报错核心根源
错误本质是代码中使用的./data是相对于进程运行工作目录(cwd)的相对路径,并非相对于代码文件本身的位置。
- 当你在模块根目录
test-main下运行测试时,进程的cwd就是模块根目录,./data可以正常匹配到实际存在的文件夹,功能完全正常。 - 当你在外层测试目录通过本地路径安装模块、再运行代码时,进程的cwd切换到了外层测试目录,系统会尝试在这个外层目录下查找
./data,自然会抛出文件不存在的错误。
当前临时修复方案的缺陷
你替换的./node_modules/random-usernames/data路径只是凑巧能在当前测试环境生效,并非可长期使用的兼容实现:
- 这本质还是基于cwd的相对路径,只要运行脚本时的工作目录不是安装你模块的项目根目录(比如用户在自己项目的
src子目录下执行脚本),路径就会直接失效。 - 现代包管理器(pnpm、Yarn PnP)不会把依赖文件平铺在项目根的
node_modules路径下,目录结构和传统npm存在差异,硬编码的这个路径在这类环境下100%无法正常访问。 - 当用户对项目做了依赖提升、外置node_modules等定制配置时,这个路径也会立刻触发文件找不到的错误。
标准修复流程
1. 锚定模块自身的资源路径
彻底抛弃依赖cwd的相对路径,基于代码文件本身的位置拼接资源路径,不受运行时目录切换的影响:
- CommonJS语法的模块,直接使用内置全局变量
__dirname,它的值永远是当前代码文件所在目录的绝对路径。 - 搭配内置
path模块拼接路径,自动适配Windows、macOS、Linux的路径分隔符,避免跨平台兼容问题。
替换原代码的示例:
const fs = require('fs'); const path = require('path'); // 定位模块自身根目录下的data文件夹 const dataDir = path.join(__dirname, 'data'); fs.readdirSync(dataDir);
- 如果是ES Module语法的模块,没有内置
__dirname变量,可以通过import.meta.url获取当前文件的绝对路径完成拼接:
import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const dataDir = path.join(__dirname, 'data'); fs.readdirSync(dataDir);
2. 保证发布包包含data目录
路径逻辑修改完成后,需要确认npm发布时会将data目录打包进正式的包文件,避免线上环境出现资源缺失:
- 在模块根目录的
package.json中,通过files字段明确声明需要打包上传的内容,将data/**/*加入数组,示例配置:{ "files": [ "lib/**/*", "data/**/*" ] } - 不建议完全依赖
.npmignore做反向排除,避免误将data目录过滤掉导致发布的包缺失资源。
内容的提问来源于stack exchange,提问作者divinelemon
相关产品推荐
相关产品推荐

