【问题标题】:Publish an NPM module in two pattern styles以两种模式样式发布 NPM 模块
【发布时间】:2017-07-24 08:19:06
【问题描述】:

我有一个包,它由 Typescript 编译为 UMD,然后由 Webpack 转换为全局变量(我们必须使用 Typescript,因此不能选择更灵活的 UMD 模式)。我希望使用包的应用程序能够选择他们需要的。这些将部署到本地 NPM 注册表。

目前我有一个 package.json,其中列出了所有必需的依赖项和构建脚本。我不介意发布两个不同的包(可能发布到不同的范围,即@my-umd-packages\my-package@my-globals-packages\mypackage,但我想为所有依赖项和脚本保留一个包,因为除了最后一步之外,它都是一样的。

最简洁的方法是什么?可以在具有不同main 属性的两个地方发布一个包吗?

感谢您的帮助

【问题讨论】:

  • 为什么会有一个带有全局变量的版本和一个带有 UMD 的版本? UMD 回退到一个全局变量,这是通用模块定义的关键部分。
  • @MichaelJungo - 不是 Typescript UMD。这里有关于这些问题和一些解决方法的讨论github.com/Microsoft/TypeScript/issues/8436
  • 好的,我在#2605看到了讨论,不应该叫UMD,但他们最终还是这样做了。

标签: npm webpack umd


【解决方案1】:

TypeScript 不会回退到全局变量,它应该是 UMD 模块的一部分。有可能发布您的包的多个版本。坦率地说,为全局变量提供一个单独的模块是相当特别的,因为大多数时候 UMD 都会参与其中。好消息是 webpack 确实支持这种模块,并且可以通过设置 output.libraryTarget 来生成它。

output: {
  filename: 'mylib.js',
  library: 'MyLibrary',
  libraryTarget: 'umd'
}

许多包发布了多个版本,例如,一个带有 ES 模块,用于 webpack 或 Rollup 等模块捆绑器,另一个在 Node 中工作(带有require)。这样做的一个很好的例子是 Redux,它有一个simple build step。它使用 Babel 为 bundle 转译 source 和 Rollup,但 TypeScript 和 webpack 的原理是一样的。

Redux 发布了三个目录(完整的发布结构参见unpkg - Redux):

dist/  # UMD bundles
es/    # ES modules version (same as lib/ but with ES modules)
lib/   # Transpiled version to work in Node

这意味着如果你想使用 UMD 版本,可以导入 redux/dist/redux.js,例如在脚本标签中,感谢 unpkg,这非常简单(希望这是全局变量的主要用途)。

<script src="https://unpkg.com/redux/dist/redux.js"></script>

此外,它定义了 the module field 将由捆绑器使用,这些捆绑器受益于 ES 模块(Rollup - pkg.module 了解详细信息),否则它将使用 lib/index.jsmain 字段)。使用 webpack,您可以配置要使用 resolve.mainFields 的字段。您可能需要考虑发布这样的结构,因为如果您只想使用它的一部分并且 ES 模块在 Webpack 中启用 Tree Shaking,则不必总是需要导入整个包,您的库的使用者会喜欢它,因为它将减小包大小。

【讨论】:

  • 很高兴知道resolve.mainFields 存在,并且在单个包中支持多个模块模式。但是,如果没有将这种支持扩展到 Typescript,当我在另一个 Typescript 文件中使用不在 index.tsindex.d.ts 中的模式时,我只会得到一个编译错误。
  • 没有什么能阻止你发布 TypeScript 源代码,你需要做的就是在 webpack 中使用 TypeScript 加载器。但是你可以从 TypeScript 中导入 JavaScript,这不是问题。要拥有类型定义,您可以发布它们并使用 typings 字段引用它们,许多包都这样做(甚至有些不是用 TypeScript 编写的,例如 Redux)。
  • Typescript 源代码只会描述有限的 UMD(仅限 CommonJS 和 AMD),自动生成的 index.d.ts 也会反映这一点。我可以手动创建一个d.ts 文件,其中包含export as namespace myModule 之类的内容,这将反映Webpack/Rollup 生成的内容。但是,如果所有内容都在一个包中,Typescript 编译器如何知道使用哪个?我可以使用相对导入语句(即import * as myModule from '../../../node_modules/my-module/globals/index',但这有一些明显的缺点。
  • 类型描述了整个公共 API,与模块的分布方式无关。
  • 所以即使在某些情况下(当您使用 UMD 时)该命名空间不存在时,包含命名空间声明的单个 index.d.ts 也是可以接受的?
猜你喜欢
  • 2015-05-25
  • 1970-01-01
  • 2020-12-31
  • 2011-11-04
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-27
相关资源
最近更新 更多