在 ES 模块构建的Nodejs中如何使用 __dirname 和 __filename
解决在使用nodejs构建`ESM`程序的时候,找不到`__filename`和`__direname`这两个变量,并且不能直接导入`JSON`文件的问题
本文章的内容在 nodejs v16 版本下测试通过。
如果要使用 ES
模块而不是 CommonJS
模块构建 Node.js
应用程序,可以通过使用.mjs
或者在package.json
中添加"type": "module"
,这样就可以使用ESM
了。
问题
在ESM
中没有了__filename
和__direname
这两个变量,并且不能直接导入JSON
文件。
如果程序中用到了__filename
和__direname
,则会遇到这样的错误ReferenceError: __dirname is not defined in ES module scope
和 ReferenceError: __filename is not defined in ES module scope
如果使用import packageConfig from "../package.json"
来导入package.json
。
你会遇到这样的错误 TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///.../package.json" needs an import assertion of type "json"
。
解决办法
通过Object.defineProperty
给global
添加loadJSON
、getFileName
和getDirName
三个函数,扩展esm
模式下的 global 属性。代码如下
// expandGlobal.js
import url from "node:url";
import path from "node:path";
import { createRequire } from "node:module";
Object.defineProperty(global, "loadJSON", {
get() {
return (filepath, importMetaUrl) => {
const reg = /\S+.json$/g;
if (reg.test(filepath)) {
const require = createRequire(importMetaUrl);
return require(filepath);
} else {
throw new Error("loadJSON 的参数必须是一个json文件");
}
};
},
enumerable: true,
configurable: false,
// writable: false,
});
Object.defineProperty(global, "getFileName", {
get() {
return (importMetaUrl) => {
return url.fileURLToPath(importMetaUrl);
};
},
enumerable: true,
configurable: false,
// writable: false,
});
Object.defineProperty(global, "getDirName", {
get() {
return (importMetaUrl) => {
return path.dirname(url.fileURLToPath(importMetaUrl));
};
},
enumerable: true,
configurable: false,
// writable: false,
});
使用
import "./expandGlobal.js";
console.log(global.getFileName(import.meta.url));
console.log(global.getDirName(import.meta.url));
console.log(global.loadJSON("../package.json",import.meta.url));
执行上述代码时,您将看到类似于以下内容的输出:
/Users/goodman/Desktop/Dev/node/node_kindacode/src/index.js
/Users/goodman/Desktop/Dev/node/node_kindacode/src
{
name: 'nodejs',
version: '1.0.0',
type: 'module',
packageManager: 'pnpm@7.5.1',
bin: { testcli: './src/cli/index.js' },
dependencies: {
......
}
}
结论
现在就可以像以前一样愉快的在 ESM
构建的 Node.js
了。
更多推荐
所有评论(0)