Javascript 如何发布双npm包(CommonJS+;模块),以便统一导入子模块

Javascript 如何发布双npm包(CommonJS+;模块),以便统一导入子模块,javascript,node.js,npm,es6-modules,commonjs,Javascript,Node.js,Npm,Es6 Modules,Commonjs,我一直在努力打包一个NPM包,这样它就可以捆绑CommonJS和ES模块,但它们都是以相同的绝对模块路径导入的。不仅是主模块 例如,我可能有一个文件包,其中两个版本在包中都有自己的或目录 /package /modules index.js submodule.js /node index.js submodule.js 我希望能够透明地导入,以便在节点或浏览器(或网页包等)上加载正确的模块 因此,调用require('package/submodule

我一直在努力打包一个NPM包,这样它就可以捆绑CommonJS和ES模块,但它们都是以相同的绝对模块路径导入的。不仅是主模块

例如,我可能有一个文件包,其中两个版本在包中都有自己的或目录

/package
  /modules
    index.js
    submodule.js
  /node
    index.js
    submodule.js
我希望能够透明地导入,以便在节点或浏览器(或网页包等)上加载正确的模块

因此,调用
require('package/submodule')
将加载
/package/node/submodule.js
,并且
从“package/submodule”导入子模块将加载
/package/modules/submodule.js

这是否有可能,尤其是在不影响消费者和使用旧版本的node时


我尝试了各种方法,比如条件导出,
type=module
,但遇到了jest+babel jest试图导入错误模块的问题。

没有很好的文档记录,也不明显,但在Node 13.7.0+中使用条件导出是可能的。不过,您的ES模块需要使用
.mjs
文件扩展名

node\u模块/package/package.json

{
    "main": "./node/index.js",
    "exports": {
        ".": [
            {
                "import": "./modules/index.mjs",
                "require": "./node/index.js",
                "default": "./node/index.js"
            },
            "./node/index.js"
        ],
        "./submodule": [
            {
                "import": "./modules/submodule.mjs",
                "require": "./node/submodule.js",
                "default": "./node/submodule.js"
            },
            "./node/submodule.js"
        ]
    }
}
node_modules/package/modules/index.mjs

export const index='mjs index';
node_modules/package/modules/submodule.mjs

export const submodule='mjs submodule';
node\u模块/package/node/index.js

exports.index='cjs index';
node\u modules/package/node/submodule.js

exports.submodule='cjs submodule';
您的软件包可以这样使用:

main.js

const{index}=require('package');
const{submodule}=require('package/submodule');
控制台日志(索引);
控制台日志(子模块);
main.mjs

从“包”导入{index};
从“包/子模块”导入{submodule};
控制台日志(索引);
控制台日志(子模块);
这是您将在节点13.11.0中获得的输出

$ node main.js
cjs-index
cjs-submodule
$ node main.mjs
(node:44920) ExperimentalWarning: The ESM module loader is experimental.
mjs-index
mjs-submodule
结节<13 对于不支持子模块的较旧版本的节点,您需要在子模块路径处创建一个文件

例如,您可以添加此存根:

node\u modules/package/submodule.js

modules.exports=require('./节点/子模块');

虽然我对我们所处的位置不太满意,但最好的选择似乎是


我按照其自述文件中所示设置了我的库,因此包中最终只有一个版本,而不是我所问的modules+commonjs双版本

我真的希望node@TomaszPluskiewicz有一个类似的解决方案,让
包/子模块
在没有条件导出的旧版本中工作,您必须将
submodule.js
放在包的根目录下(或重新导出
node/submodule.js
的存根)。这对于普通的CommonJS加载程序来说是可行的,但这就是重点。我已经在根目录中有了
子模块.js
,它将导出模块。