几天前在Liferay,我们需要使用p-map包。只有一个问题:我们的应用程序仍然使用CommonJS格式,而P-MAP仅发布ES6 modules。即使我发现的一些最好的参考文献(例如this post)也明确表明,不可能从Commonjs导入ES6模块。
好消息是,这不再是真的!使用dynamic koude0,我们可以从commonjs加载ES6模块。让我们看一个例子。
在此project中,koude1文件试图使用require()
导入ES6模块:
const pmap = require('p-map');
exports.importer = () => {
console.log('Yes, I could import p-map:', pmap);
}
当然没有工作:
$ node index.js
internal/modules/cjs/loader.js:1102
throw new ERR\_REQUIRE\_ESM(filename, parentPath, packageJsonPath);
^
Error \[ERR\_REQUIRE\_ESM\]: Must use import to load ES Module: /home/adam/software/es6commonjs/node\_modules/p-map/index.js
require() of ES modules is not supported.
require() of /home/adam/software/es6commonjs/node\_modules/p-map/index.js from /home/adam/software/es6commonjs/importer.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/adam/software/es6commonjs/node\_modules/p-map/package.json.
at new NodeError (internal/errors.js:322:7)
at Object.Module.\_extensions..js (internal/modules/cjs/loader.js:1102:13)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module.\_load (internal/modules/cjs/loader.js:790:12)
at Module.require (internal/modules/cjs/loader.js:974:19)
at require (internal/modules/cjs/helpers.js:101:18)
at Object.<anonymous> (/home/adam/software/es6commonjs/importer.js:1:14)
at Module.\_compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module.\_extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32) {
code: 'ERR\_REQUIRE\_ESM'
}
解决方案是将require()
转换为动态import
,这是一种语法,我们调用import
命令,就好像它是一个异步函数一样。但是有一个细节:导入导入返回Promise
s。有很多方法可以解决这个问题。最简单的可能是使我们的功能异步,例如this version:
exports.importer = async () => {
const pmap = await import('p-map');
console.log('Yes, I could import p-map:', pmap);
}
现在我们的小应用程序可行!
$ node index.js
ok
Yes, I could import p-map: \[Module: null prototype\] {
AbortError: \[class AbortError extends Error\],
default: \[AsyncFunction: pMap\],
pMapSkip: Symbol(skip)
}
可能需要其他一些调整。 (例如,我必须调整eslint设置。)重要的是这是可能的。这不是一个kludge:Node’s own documentation recommends this approach。
因此,不要因为过时的信息而害怕:至少目前,您需要将整个应用程序重写为ES 6模块。对我们来说,这是一个宽慰!https://suspensao.blog.br/disbelief/importing-es-6-modules-from-commonjs/
(来自Wikimedia Commons的封面图像。)
(Importing ES 6 Modules from CommonJS帖子首次发表在Suspension of Disbelief中。)