Bower 和 npm 事实上是 Web 的包管理器。 我怀疑很少有前端开发人员没有听说过它们或使用它们来管理依赖项。
虽然我们许多人都是作为使用者使用它们,但有一天你可能会决定分享你自己的项目并成为贡献者! 最近我就遇到了这种情况。 我有在 npm 和 Bower 上发布 我的开源库 的经验。
尽管它们的官方文档非常好,但我仍然在三个鲜为人知的问题上遇到了困难。 我不会在这篇文章中关注基础知识。 你可以随时 找到并阅读相关信息。 我将重点关注这些问题。
如今,看起来即使是 Bower 也 建议人们不要使用 Bower。 然而,在 2018 年,仍然有许多项目依赖于它。 2017 年 JavaScript 现状调查 显示,大约 24% 的受访开发人员仍然使用 Bower 作为包管理器。 因此,我认为在看到 Bower 的终结之前可能还需要一段时间,这意味着可能仍然值得支持它以涵盖遗留包管理的项目。 我理解那些在遗留项目上工作的人的痛苦——这就是为什么我也选择在那里发布我的开源模块的原因。
我希望在阅读本文之后,当你决定与世界分享你的代码时,你会领先一步。 闲话少说,以下是在管理包时我遇到的一些问题。
从 npm 中删除包
为什么要花几个小时来选择一个名称,而不能先专注于发布功能呢? 在我第一次使用 npm 的经历中,我不幸地将我的项目名称命名为“test-something”。
猜猜怎么了? 几天后,我发现 npm 公共注册表中的取消发布选项仅允许取消发布过去 24 小时内发布的版本。 如果你试图取消发布一个发布超过一天的版本,那么你必须 联系支持人员。
他们表示,删除其他人员依赖的库通常被认为是不好的做法。 我理解这一点,但我 100% 确定没有项目依赖于名为“test something”的包。
我本来打算置之不理,但我的测试包将永远显示在我的闪亮的
我联系了支持人员,他们在同一天处理了我的请求。 他们仍然不想完全取消发布它,但他们确实将其转移到 @npm 用户帐户并将其弃用,并附带弃用说明。 这将其从我的个人资料(太棒了!)和搜索结果中删除。 但是,如果有人知道确切的 URL(或名称),他们仍然可以安装它。 虽然这并不完全理想,但弃用说明仍然会提醒用户该包不再受支持。
我认为这可能与 Azer Koçulu 从 npm 中删除的 11 行代码有关,这导致互联网短暂崩溃。 安全第一。
故事的寓意:确保明智地选择包名称!
导出模块
我遇到的另一个问题是 如何导出我的模块。 我希望以一种通用的方式来做,以便任何人都可以将其导入到浏览器中,使用三种最流行的方法中的任何一种。 例如…
…使用 ES6
// If a transpiler is configured (like webpack, Babel, Traceur Compiler or Rollup):
import MyModule from 'my-module';
…使用 CommonJS
// If a module loader is configured (like RequireJS, Browserify or Neuter):
const MyModule = require('my-module');
…或通过在 HTML 中引用脚本文件
<script ="/node_modules/my-module/index.js"></script>
我实际上正在寻找的是 通用模块定义 模式。 这种模式提供了一种干净的方式来将你的模块暴露给以各种方式使用模块的不同环境。
这种模式有几种变体,具体取决于你真正需要什么。 但是,以这种方式编写的模块能够在任何地方工作,无论是在客户端、服务器端还是其他地方。
标准模式是
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['dependency'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('dependency'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.dependency);
}
}(this, function (dependency) {
// Use dependency in some fashion.
return {
// Your module goes here
};
}));
如果你正在使用 Grunt、Gulp 或 webpack,你会发现有一个插件可以为你包装你的模块。 此外,它 已经包含在 webpack 的核心之中!
管理分发文件
这个真的很难。
我正在为 npm 和 Bower 构建一个包。 我遵循了将工作文件(ES6)保存在 src/
包目录中,并在 dist/
目录中构建我的分发文件(ES5,使用 Babel 编译)的模式。
我在 .gitignore
文件中忽略了整个 dist/
文件夹。 你知道流程:源代码控制应该只包含源代码。 如果它是从源代码生成的,那么它就不属于那里——而应该由你的构建过程生成。
一方面(npm),我有一个 .npmignore
,它恰好做相反的事情,忽略 src/
而不是 dist/
。 在 npm 上,我只想要我的分发文件。 这运行得非常好。
另一方面(Bower),存储库中缺少 dist/
文件夹,因此 Bower 包不包含它。 你看,Bower 只跟踪你公开可用的 Git 端点。 通过推送 Git 标签,你在 Bower 注册表上发布新版本。 是的,它可以忽略文件,但它们仅与存储库中的文件相关。
那么,我如何才能在 Bower 上发布 Git 忽略的 dist/
文件夹内容呢?
我不确定是否可以做到。 我找到的唯一解决方法是在存储库中提交分发文件。 如果你真的想将这些分发文件保留在存储库之外,诀窍是在发布标签之前提交它们。 发布标签。 删除它们。
还有一个用例让我感到安心。 想象一下,有人下载了你的存储库的 ZIP 文件并将其放入他们的项目中。 他们不需要你的花哨构建步骤。 生产源代码已经存在。 好吧,也许这并没有那么糟糕。
总结
即使 Bower 即将退出,npm 和 Bower 仍然被广泛使用,并且是管理项目依赖项的有用方法。 虽然它们在各自领域都表现出色,但作为列在任一包目录中的包的所有者和贡献者,对我们来说也提出了一些挑战,我希望我在这里概述的内容可以帮助其他人节省一些时间并避免潜在的麻烦。
你是否知道处理此处介绍的问题的其他方法? 或者你是否也遇到过类似的问题? 请在评论中告诉我!
如果你有 bower,你就有 npm。 Bower 实际上被标记为“已弃用”,并在安装时会发出警告。
所有这些都足以成为避免向其发布任何新包的理由,即使你的旧项目仍然可以使用它,而无需“升级”到 npm。
Bower 事实上的包管理器? 嗯……现在甚至 Bower 的网站也告诉人们不要使用它,而要使用 Yarn 和 Webpack。
我从来不喜欢你那里提供的通用定义模式。 它有效,但它读起来有点让人困惑。 它们都做着同样的事情,但 对我来说,这个更容易理解。 Gist 中 的突出显示行显示了魔法发生的部分。 你可以通过使用 Webpack 来避免整个通用定义模式的问题。 Webpack 有关于使用它编写库的文档。 然后你可以编写最新的 JavaScript 语法,将其转换为 es5,并获得所有互操作性,而无需测试库的多个版本。
你应该看看 Rollup,这是一个很棒的模块打包器,可以输出你指定的任何格式(amd、commonjs、umd)。
https://github.com/rollup/rollup
是否可以使用 ES6 导入 UMD 模块? 我知道我们可以将 ES6 导入语句编译成 ES5,这无论如何都会
require
模块,但我们能否为原生 ES6 导入以及 CommonJs 和 AMD 导出模块?