【问题标题】:How can I publish an NPM module with both commonjs and es6 versions?如何发布同时具有 commonjs 和 es6 版本的 NPM 模块?
【发布时间】:2020-07-27 18:43:27
【问题描述】:

我有一个要发布到 npm 的模块。我发现了一些 4 年以上的“解决方案”、使用 babel 5.x 的示例以及其他导致示例无法正常工作的问题。

理想情况下,我想使用 es6 编写代码并使用 babel 构建/转换,以便可以在脚本中使用 require() 或在模块中使用 import 导入。

现在,这是我的(示例)模块,展示了我尝试过的内容。

// index.js
export default function speak () {
  console.log("Hello, World!");
}
// .babelrc
{
  "comments":false,
  "presets": [
      ["@babel/env", {"modules": "commonjs"}]
  ],
  "plugins": [
    "@babel/plugin-transform-modules-commonjs",
    "add-module-exports"
  ]
}
// package.json
{
  "name": "foo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "babel index.js -d dist"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.10.5",
    "@babel/core": "^7.10.5",
    "@babel/plugin-transform-modules-commonjs": "^7.10.4",
    "@babel/preset-env": "^7.10.4",
    "babel-plugin-add-module-exports": "^1.0.2"
  }
}

最后,还有一个演示脚本 (demo.js)

// demo.js
const speak = require('./dist/index.js');
speak();

当我执行npm run build 然后node demo.js 时,它按预期工作:

Hello, World!

我也希望能够拥有一个模块(将"type":"module" 添加到package.json),然后以这种方式使用demo.js 文件:

import speak from './dist/index.js';
speak();

但是,我收到默认导出不可用的错误:

import speak from './dist/index.js';
       ^^^^^
SyntaxError: The requested module './dist/index.js' does not provide an export named 'default'

我并不关心答案是什么,我只想知道最佳实践是什么。我应该只导出为 ES6 吗?我应该只需要commonjs吗?有没有办法用两个可用目标进行转译?

注意:

  • 节点 v14.5.0
  • npm v6.14.6
  • @babel/core v7.10.5

【问题讨论】:

    标签: javascript node.js npm babeljs transpiler


    【解决方案1】:

    您可以将webpackrollup 之类的捆绑程序与babel 结合使用。它们提供了编译到多个目标的选项。通常任何库代码都会编译到以下目标:

    1. ESM 或 MJS(Ecmascript 模块)
    2. UMD(通用模块)

    也可以编译成CJS(CommonJS模块)或IIFE(立即调用函数表达式)。

    如今,UMD 和 ESM 非常标准(尤其是 UMD,因为它是 IIFE、CJS 和 AMD 的组合)。

    您可以浏览 Webpack 或 Rollup 的官方文档。但是,我创建了一个工具,您可以使用它来实现您正在寻找的输出。 https://www.npmjs.com/package/rollup-boilerplate

    你可以检查它,玩弄它,破解它。我认为这可能是一个很好的起点。您可以查看这篇文章以开始使用:https://medium.com/@contactsachinsingh/setting-up-a-rollup-project-under-two-minutes-fc838be02d0e

    【讨论】:

    • 谢谢——这很有帮助。我的印象是 rollup 和 webpack 都是针对浏览器的。不是这样吗?
    • 不!事实并非如此。 Rollup 和 Webpack 的目的只是捆绑可以以某种方式使用的代码。无论您是在客户端项目还是服务器端工作都没有关系。
    • 好的,这是一个巨大的帮助(尤其是你的汇总样板模块,谢谢!)。我会玩汇总并尝试弄清楚。当我require 模块时它工作正常,但是当我导入它时,我必须从模块中的 ./dist/umd/index.js' 路径导入。关于如何处理的任何想法?
    • 您正在使用@babel/plugin-transform-modules-commonjs 将您的代码转换为与require 一起使用的CommonJS。您可以做两件事:删除此插件并使用--experimental-modules 标志。例如。 node index.js --experimental-modules,或使用捆绑器。
    • 理想情况下,您应该以 UMD 和 ESM 格式发布代码,在 package.json 中指定 mainmodule 路径,这样就很好了。 CommonJS 模块系统将选择 UMD 版本(main 路径)。对于网络,您可以使用 ESM(module 路径)。您也可以使用 UMD 网页版,但不适用于 <script type="module">。您可以将其作为常规脚本文件导入。
    猜你喜欢
    • 2016-03-01
    • 2015-06-26
    • 2016-04-15
    • 2020-05-18
    • 2012-12-17
    • 2020-08-18
    • 2021-07-18
    • 2017-05-16
    • 2018-08-04
    相关资源
    最近更新 更多