将ES模块(.mjs)发布到NPMJS,并向后兼容节点<8.5.0
直到Node v8.5.0,将一个用ES6编写的模块发布到NPMJS中是一个简单的过程:使用Babel这样的工具来转换ES6代码,然后将结果的lib
目录发布到NPMJS,而你的GitHub仓库包含src
文件。
在v8.5.0中,Node已经通过--experimental-modules
标志发布了本地模块 ( export
/ import
)的实验支持 。 现在可以将纯ES6模块发布到NPMJS上 ,只要涉及的文件具有.mjs扩展名,就可以在不进行任何转换的情况下使用它们 。
如何发布ES6模块( .mjs ),以便它也可以用于不支持ES本地模块的旧版本的Node?
诀窍是不要在package.json main
条目中指定一个确切的path。 而是使用扩展less的main
条目,或者在包的根目录提供index.js
和index.mjs
。
选项1 – 无扩展主:
如果不包含扩展名,节点将dynamic使用.mjs
扩展名(如果可用并使用ES6加载程序)或在.js
回退。
"main": "lib/entry"
这将在ES6模块模式下parsing为lib/entry.mjs
,或者在CommonJS模式下parsing为lib/entry.mjs
,如果MJS文件不可用,ES6加载器将回退到CommonJS版本。
选项2 – 使用index.mjs
和index.js
代替:
如果你的包提供了一个根index.mjs
和index.js
,当import
-ed时,Node将会更喜欢index.mjs
,而当require
-ed时仍然使用index.js
(如果没有提供index.mjs
,ES6加载器将使用index.js
)。 这意味着您可以提供来自index.mjs
的ES6模块版本和来自index.js
的CommonJS转译版本。
可能的问题:
如果你的软件包的用户同时使用ES6和CommonJS模块,并希望他们引用同一组对象,那么我可以想到一个潜在的问题。 在某些边缘情况下,这可能是一个问题,但使用完全相同的模块实例的多个包永远不会被给出,因为不同的包可能需要包的不同版本。
例:
示例项目:
index.mjs
import testmod from 'testmod'; console.log(testmod);
index.js
const testmod = require('testmod'); console.log(testmod);
node_modules/testmod/package.json
{ "name": "testmod", "version": "1.0.0" }
在这个文件中,你可以select使用一个扩展名较less的main
条目,如下所示:
{ "name": "testmod", "version": "1.0.0", "main": "index" }
node_modules/testmod/index.mjs
export default { from: 'index.mjs' };
node_modules/testmod/index.js
module.exports = { from: 'index.js' };
示例输出(ExperimentWarning省略):
$ node --experimental-modules index.mjs { from: 'index.mjs' } $ node --experimental-modules index.js { from: 'index.js' } $ node index.js { from: 'index.js' }