【问题标题】:How to publish dual npm package (CommonJS + modules) so that submodules are uniformly imported如何发布双npm包(CommonJS + modules),使子模块统一导入
【发布时间】:2020-05-18 13:32:23
【问题描述】:

我一直在努力打包一个 NPM 包,以便它捆绑 CommonJS 和 ES 模块,但要么使用相同的绝对模块路径导入。不仅是主模块。

例如,我可能有两个构建在包中都有它们的 or 目录

/package
  /modules
    index.js
    submodule.js
  /node
    index.js
    submodule.js

我希望能够透明地导入,以便在节点或浏览器(或 webpack 等)上加载正确的模块。

因此,对require('package/submodule') 的调用将加载/package/node/submodule.js,而import submodule from 'package/submodule' 将加载/package/modules/submodule.js

这完全有可能吗,尤其是它不会影响消费者并适用于旧版本的节点?

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

【问题讨论】:

    标签: javascript node.js npm es6-modules commonjs


    【解决方案1】:

    这不是很好的文档或显而易见的,但在 Node 13.7.0+ 中使用条件导出是可能的,这与the way you would for the main entry point 不同。不过,您的 ES 模块将需要使用 .mjs 文件扩展名。

    node_modules/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_modules/package/node/index.js

    exports.index = 'cjs-index';
    

    node_modules/package/node/submodule.js

    exports.submodule = 'cjs-submodule';
    

    比你的包可以这样使用:

    main.js

    const {index} = require('package');
    const {submodule} = require('package/submodule');
    
    console.log(index);
    console.log(submodule);
    

    main.mjs

    import {index} from 'package';
    import {submodule} from 'package/submodule';
    
    console.log(index);
    console.log(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
    

    节点

    对于不支持子模块的旧版本节点,您将需要一个位于子模块路径的文件。

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

    node_modules/package/submodule.js

    modules.exports = require('./node/submodule');
    

    【讨论】:

    • 我真的很想为节点
    • @TomaszPluskiewicz 要让package/submodule 在没有条件导出的旧版本中工作,您必须将submodule.js 放在包的根目录(或重新导出node/submodule.js 的存根) .这适用于常规的 CommonJS 加载器。
    • 这就是重点。我已经在根目录中有submodule.js,它会导出模块。
    【解决方案2】:

    虽然我对我们所在的地方不太满意,但最好的选择似乎是esm

    我按照自述文件中所示设置了我的库,所以最终包中只有一个构建,而不是我询问的模块+commonjs 双重构建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      • 2023-01-23
      • 1970-01-01
      • 2018-06-22
      • 2017-12-29
      • 2016-05-25
      相关资源
      最近更新 更多