在针对 ESM 和 CJS 的基于 Typescript 的项目中,如何将“动态导入的顶级等待”转换为“同步需求”?

问题描述 投票:0回答:1

我正在创建一个小型 Node.js 库,其源代码是用 TS 编写的,并且(理想情况下)生成的 JS 以 ESM 和 CJS 格式分发。

它有一个对等依赖项(当前为 CJS),我需要检测它是否已安装,如果没有则在继续之前提供后备。因此,我无法静态导入它,并且似乎需要在 ESM 发行版中使用动态

import
和 CJS 发行版中的
require
来检测它。

为了避免动态

import
迫使我将 Promise 导出给消费者,我正在考虑在 ESM 发行版中使用顶级
await
(因为自 Node 14.8.0 以来它一直支持未标记,这里的用例是类似于 tc39 提案中的这个)。所以生成的 JS 看起来像这样

ESM:

try {
    peerExport = await import("the-cjs-peer-dependency") //Notice this isn't inside of an async block
}

CJS:

try {
   peerExport = require("the-cjs-peer-dependency")
}

现在我有 2 个 tsconfig.json,一个用于 ESM,一个用于 CJS,我的源 TS 看起来与生成的 JS 的 ESM 版本一模一样。

我正在努力解决的是如何在 CJS 构建过程中用

await import
替换
require
,因为 TS 立即给出了一个硬停止,即 CJS 不支持顶级等待并获胜”继续。到目前为止,我还没有在 Typescript 的设置中找到任何可以启用此替换的内容,只有这个相关的 Github 问题用于解决想要按原样从 CJS 动态导入 ESM 模块的反向问题。

我当前的计划是添加构建前/构建后步骤来扫描我的 TS 源并执行查找和替换,然后运行 tsc,然后恢复源,尽管这看起来不太好。对于这个特定问题或尝试从单个 TS 源代码库支持 ESM/CJS 的更大问题的任何想法将不胜感激。

谢谢

javascript node.js typescript async-await es6-modules
1个回答
0
投票

我认为我最近编写的一个库import-sync满足了这个用例

该库是 esm 的包装器,支持从 ES6 和基于 CJS 的 NodeJS 项目导入 ESM。


对于基于 CJS 的 NodeJS 项目:

/*
 * index.js/index.cjs
 */
const importSync = require('import-sync');
const { sum } = importSync('./sum.js');
console.log(sum(2,3)); // prints 5

对于基于 ESM 的 NodeJS 项目:

/*
 * index.mjs/index.js with "type": "module" in package.json
 */
import importSync from 'import-sync';
const { sum } = importSync('./sum.js');
console.log(sum(2,3)); // prints 5

文件

sum.js
可以是CJS或ESM -
importSync
将同步动态导入模块。

希望这有帮助:)。

© www.soinside.com 2019 - 2024. All rights reserved.