我维护一个用 Typescript 编写的库,我想同时针对 CommonJS 和 ESM。为此,我运行了两次构建。这需要我编写对两者都有效的代码(在 Typescript 中)。
一个问题是 CommonJS 有一个
__dirname
变量,我用它来相对地加载文件。 __dirname
在 ESM 中不存在,所以我尝试做这样的事情:
const _mydirname = typeof __dirname !== 'undefined'
? __dirname
: path.dirname(url.fileURLToPath(import.meta.url));
// Example usage
const file = fs.readFileSync(path.join(_mydirname, '../README.md'), 'utf-8')
不幸的是,在 Typescript 中构建它时,它会发出以下错误:
Error: src/application.ts(22,36): error TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.
有没有办法获取相对于当前脚本的路径,该路径在两种情况下都有效?
我不认为有任何统一的方法来获取 CommonJS 和 ESM 的当前脚本路径。
如果你无论如何都要构建它两次,你可以添加一些条件构建时间逻辑来为每个模块系统生成适当的代码,实际的实现将取决于你的打字稿构建系统。
import.meta.url
转换为 cjs.更新(如前所述,这在 cjs 中不起作用):
const _mydirname = typeof __dirname !== 'undefined'
? __dirname
// @ts-ignore
: path.dirname(fileURLToPath(import.meta.url));
我有同样的问题,实际上我正在使用这个替代品。
// src.index.ts
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
let dir;
try {
dir = __dirname;
} catch (e) {
dir = dirname(fileURLToPath(import.meta.url));
}
console.log(dir);
// tsup.config.js
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
dts: true,
format: ["esm", "cjs"]
});
// tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"moduleResolution": "node",
"module": "ESNext",
"outDir": "dist",
"esModuleInterop": true,
"declaration": true,
"sourceMap": true
},
"include": [
"src"
],
}
// package.json
{
"main": "dist/index.js",
"exports": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"types": "dist/index.d.ts",
"scripts": {
"dev": "tsup --watch",
"build": "tsup"
},
"devDependencies": {
"tsup": "^6.7.0",
"typescript": "^4.9.4",
}
}
这似乎适用于
tsup
。有一个警告,但构建成功。我不确定我使用了最佳实践......
其他想法?
编辑: 好吧,看来
tsup
有一个干净的解决方案。
https://tsup.egoist.dev/#inject-cjs-and-esm-shims
// tsup.config.js
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
dts: true,
format: ["esm", "cjs"],
shims: true
});