【问题标题】:How to choose 'module' instead of 'main' file in package.json如何在 package.json 中选择“模块”而不是“主”文件
【发布时间】:2019-03-01 18:32:38
【问题描述】:

我创建了一些 npm 模块并将它们编译为:

  • commonJS(使用exports.default =)和
  • esm(使用export default

我这样设置我的 package.json:

main: "index.cjs.js",
module: "index.esm.js"

当我 npm install 包并简单地导入它时:

import myPackage from 'my-package'

它会自动选择main文件,而不是模块。

我的问题:

在 JavaScript 文件中执行 import myPackage from 'my-package' 时,有没有办法导入 module 文件?

为什么我为“main”选择commonJS文件:

我注意到使用 Node,导入 esm 文件是不可能的,因为 export default,它必须是 commonJS。我有一些简单的辅助 JS 函数,例如 thisthis,我希望它们能够用于最广泛的受众。这就是为什么我选择 cjs 作为 package.json 中的 "main" 路径的原因。

为什么我在 package.json 中定义一个单独的“模块”:

许多像 Vue.js 这样的著名库已经在这样做了。查看有关此 Stackoverflow 线程的更多信息:

What is the "module" package.json field for?

为什么我希望能够导入“模块”文件而不是“主”文件:

目前有一个bug in Rollup 在导入cjs 文件后编码时无法正确显示JSDoc cmets,但在导入es 文件时它确实工作。 p>

我想避免的解决方法:

只需将“main”设置为 package.json 中的 esm 文件,对吗?但是,所有在 Node 应用程序中使用我的包的用户将无法再使用它......

→ 我对这一切也很困惑,但我认为我做了足够的研究来理解这一切。话虽如此,如果有人知道更好的方法或任何其他建议,请在下面的 cmets 中告诉我!

【问题讨论】:

  • 我不认为 'module` 是 package.json 的有效键。您可能想使用此处解释的内容来解决问题:stackoverflow.com/a/16631079/1971378。我已经在回答中详细说明了这一点。希望对您有所帮助。
  • ...重新考虑是否有理由不将main 直接指向index.es.js
  • @82Tuskers 感谢您的链接,但您的回答有点“不妥”。首先,package.json 中的module 被许多著名的库和框架广泛使用。其次,您的链接指向如何导出不同函数的解释......我说的是编译为 CommonJS 和 ES5 的相同函数。最后,我将 main 指向 commonJS 的原因是为了确保它在本地也可以与 node 一起使用。如果我指向 index.es.js 文件 - 它使用 export default - 节点将不会运行它。
  • 目标是什么?如果你在 Node 中使用这个模块,那么你应该配置 main 指向“模块”脚本。如果您在浏览器中使用它,则由您决定如何将其交付给客户端,而不是 package.json
  • @JakeHolzinger 哦?根据我的经验,节点无法导入编译为 es5 的文件(使用 export default),而只能导入 commonJS 编译文件。这就是我设置main: "index.cjs.js" 的原因。 >“如果您在浏览器中使用它,那么您可以选择如何将其交付给客户端,而不是 package.json”我不确定您的意思。如果我写一个人们可以npm iimport x from 'my-pkg' 的小型JS 辅助函数,那么JavaScript 会自动选择设置在"main": 的文件,我认为你不能选择另一个inpoint。这正是我的问题! : D

标签: javascript npm node-modules package.json


【解决方案1】:

只是不要对主文件使用扩展名,并且将 es6 和 CommonJS 版本作为两个单独的文件,同名,在同一目录中,但扩展名不同,所以:

index.js // transpiled CommonJS code for old nodejs
index.mjs // es6 module syntax

package.json:

{
  "main": "index"
}

如果节点以--experimental-modules 标志启动,它将使用*.mjs 文件,否则*.js

【讨论】:

  • 作者建议他们希望他们的辅助函数“可用于最广泛的受众”,而 .mjsnot associated,据我所知,可以使用任何脚本媒体类型。
  • 有谁知道为什么在基于浏览器的应用程序(例如 React)中使用 require() 不会选择模块选项而不是 main?
  • 您可以在基于浏览器的应用程序 b/c 中使用 require(),它与 webpack 之类的东西捆绑在一起。您的捆绑器配置将确定使用什么类型的模块。
【解决方案2】:

Nodejs 不支持“模块”,但支持较新的“导出”规范。

https://nodejs.org/api/packages.html#exports

https://github.com/nodejs/node/blob/v16.14.0/lib/internal/modules/esm/resolve.js#L910

  "exports": {
    "import": "./main-module.js",
    "require": "./main-require.cjs"
  },

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2022-07-25
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2019-09-13
    • 2019-09-06
    相关资源
    最近更新 更多