在这篇文章中,我们将通过学习如何使用 Jspm 包管理器及其相关的 SystemJs 模块加载器(示例代码可 在此处 获得)来了解 ES6 模块化的当前状态。我们将讨论以下主题:
- 今天使用 ES6 模块
- 为什么模块化在 Javascript 中很重要
- Jspm 包管理器以及今天如何使用它
- 使用 Jspm 创建一个随时可用的包
- SystemJs 模块加载器
- Jspm 与 Bower
- Jspm 与 npm
- 结论
今天使用 ES6 模块
ES6 模块化的主要目标之一是使从 Internet 上的任何地方(github、npm 等)安装和使用任何 Javascript 库变得非常简单。只需要两件事:
- 安装库的单个命令
- 一行代码导入库并使用它
想象一个世界,您可以使用如下命令安装库:
jspm install jquery
然后用一行代码导入库,就可以开始使用了:
jspm install jquery
事实证明, 今天 这实际上可以通过 Jspm 及其相关的 SystemJs 模块加载器实现,而无需任何进一步的工具。
请注意,如果使用像 Babel 这样的转译器,上面的导入也可以在 ES6 语法中完成:
jspm install jquery
我们将看到这一切是如何工作的,以及它是如何真正易于使用的。
为什么模块化在 Javascript 中很重要?
模块化在 Javascript 中很重要,原因与它在任何其他语言中的重要性相同:
- 它鼓励开发具有清晰接口的小型隔离模块,而不是大块的单一代码
- 它有助于提高可测试性,因为模块可以在运行时替换为实现相同接口的模拟
- 它提高了代码的可维护性,因为更小且隔离良好的模块更容易理解
Jspm 解决的基本问题
当项目达到一定规模时,他们迟早要处理“依赖地狱”问题。当同时需要同一个库的两个不同版本时,就会发生这种情况。
与依赖管理相关的另一个问题是确保我们始终拥有库版本的有效组合,这意味着如果我们需要一个本身具有依赖的库,则应该为我们透明地下载并包含该传递依赖。
所有这些问题都由 Jspm 透明地处理:它允许同一个包的多个版本,它甚至支持循环依赖。
Jspm 包管理器实战
正如我们提到的,为了安装一个库,我们只需要一个命令。可以从多个来源安装库,例如从 github 或 npm。让我们安装几个库:
jspm install jquery
安装命令负责下载整个依赖关系树,并将其以版本化平面树的形式复制到文件系统中,如下所示:
jspm install jquery
Jspm 不仅安装依赖项,而且还知道模块加载和捆绑。乍一看这似乎很奇怪,因为这些任务通常由不同的工具处理。但结果非常强大:我们可以用一个命令创建一个随时可用的 javascript 包:
jspm install jquery
此命令创建一个自执行和缩小的包,其中执行入口点是文件
src/main.js
。 Jspm 将跟随该文件的导入并递归地捆绑所有需要的 Javascript 文件。
结果是一个随时可用的包,可以像这样在网页上使用:
jspm install jquery
请注意,我们设法使用了所有依赖项,甚至没有考虑配置模块加载器。
SystemJs 呢?
您是否注意到到目前为止 SystemJs 模块加载器无处可寻?这是因为 Jspm 了解 SystemJs,并将透明地安装它,将其包含在自执行包中并使用它来加载应用程序的入口点。
这非常强大:我们今天可以在生产中以透明的方式使用 ES6 模块。即使在纯 ES5 项目中(使用 require 语法),这一切都可以正常工作。
什么是 SystemJs 模块加载器?
SystemJs 是一个通用模块加载器,能够加载不同格式的模块:AMD、CommonJs、globals。它适用于节点和浏览器。
SystemJs 由一个 ES6 模块加载器 polyfill 和一个允许它使用不同模块格式的兼容层组成。 SystemJs 可以独立于 Jspm 使用,但这两个工具最好一起使用。
独立于 Jspm 使用 SystemJs 与 Bower + Browserify 或 Bower + Webpack 等其他解决方案相比并没有那么多优势。您仍然需要使用另一个包管理器下载依赖项并配置构建工具来创建包。您还需要安装模块加载器并学习如何配置和使用它。
使用 Jspm,我们基本上可以或多或少地忘记正在使用的模块加载器,而只需使用 ES6 导入语法(或 ES5 等效语法)。
Jspm 与 Bower
Jspm 和 Bower 的构建理念截然不同。 Bower 基于这样的假设,即浏览器中同时只能有一个版本的库。
Bower 会将传递依赖项下载到平面树中,但如果需要同一库的两个版本,它会询问用户应该选择哪个版本。 Bower 允许将该决定保存到
bower.json
中,以便其他用户可以拥有可重现的构建。
Jspm 是为这样一个世界而设计的:开发人员构建许多可以重复使用的小的不同前端模块,类似于 npm 世界中发生的事情。为了解决这个问题,可以独立加载同一模块的多个版本而不会发生冲突,但用户最终可以根据需要控制这些决定。 SystemJs 甚至可以处理循环库引用!
Jspm 与 Npm
综上所述,趋势是 npm 越来越成为所有 Javascript 的包管理器,包括前端。
越来越多的前端库通过有意义的 CommonJs 导出发布到 npm,但这些库不能在节点中使用,因为它们通常需要 DOM。目标是让 CommonJs 模块易于安装,以便前端库可以被 browserify 或什至 SystemJs 使用,并在浏览器而不是节点中使用。一个发布到 npm 的前端库是例如 AngularJs 。
npm 团队正计划让 npm 对前端更加友好。 Angular 团队已经或将要让 npm 成为如何实现这一目标的具体 建议 。
Npm 几周前刚刚发布了第 3 版,并且只有在这个最新版本中,他们才实现了最大平坦的依赖树。这无疑是帮助覆盖前端模块化的良好开端,但 Jspm 在这方面拥有巨大的领先优势,并且背后有很大的动力。
结论
Jspm 允许今天已经使用的 ES6 模块,如果需要的话甚至可以使用 ES5 语法。尽管 SystemJs 模块加载器可以单独使用,但如果您通过 Jspm 透明地使用它,您将真正受益匪浅。
在概念和功能方面,Jspm 和 SystemJs 远远领先于其他类似工具。 Jspm/SystemJs 不仅功能更多,而且实际上使用起来也简单得多,尤其是在上面介绍的自执行捆绑场景中。
相关链接
以下帖子对 Bower、Jspm 和 npm 进行了深入比较 - Bower 死了吗?什么是JSPM?客户端的 Npm?
Jspm、SystemJs 和 ES6 模块加载器 polyfill 的创建者 Guy Bedford 的演讲深入探讨了 Jspm 和 SystemJs - ES6 模块的包管理
此外,可以 在此处 找到这篇文章中的代码,其中包含用于首次查看 Jspm 运行情况的运行说明。