原文:https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modularjavascript

解耦应用的重要性

在弹性 JavaScript 世界中,当我们称一个应用为 模块化的 ,我们通常是指它是由一组存储在模块中的高度解耦、不同功能的部分组成。解耦 通过在可能的情况下移除依赖,以提高应用的可维护性。在正确解耦的情况下,我们可以很容易看出来系统中某部分的改动会如何影响其他部分。

然而与一些更传统的编程语言不同,JavaScript 当前的版本(ECMA-262)没有提供给开发者一个干净、有组织的方法来导入这些代码模块。直到近些年来,对更有组织化的 JavaScript 应用的需求变得明显,使得支持模块化就变成了规范的关注点之一。

然而,开发者目前只能借助于模块 的变体或者是对象字面量模式 来实现模块化,我们随后将讲到这些方式。其中的大多数方法中,模块脚本通过声明在单个全局对象下的命名空间与 DOM 串联在一起,这样架构仍然可能会导致命名冲突的问题。如果不手工维护或者不借助第三方库的话,仍然没有一个简洁的方式来处理依赖管理。

尽管用于解决这些问题的原生方案将要与 ES Harmony 一起到来(它可能是下一代 JavaScript),好消息是编写模块化的 JavaScript 从来就没容易过,我们可以从现在开始做。

在本节中,我们将学习三种用于编写模块化 JavaScript 的格式: AMDCommonJS 和可能是下一版本 JavaScript 的 Harmony

关于脚本加载器的提示

如果不讨论房间中的大象 - 脚本加载器 ,我们就很难讨论 AMD 和 CommonJS 模块。在编写本书时,脚本加载是实现目标的一种手段,这个目标就是让模块化 JavaScript 能在今天的应用中使用,为此,不幸的是必须要使用兼容的脚本加载器。为了更好的读懂本节内容,我建议你去对流行的脚本加载工具做一个 基本的了解 ,这样模块格式的说明在上下文中才更有意义。

用于处理 AMD 和 CommonJS 格式中的模块加载的加载器有很多好用的,但是我个人倾向于 RequireJScurl.js。这些工具的完整教程不在本书的讨论范围内,但是我推荐你去阅读 John Hann 关于 curl.js 的 文章 和 James Burke 关于 RequireJS 的接口文档 来了解更多信息。

从生产的角度来看,当与这样的模块工作时,推荐发布使用优化工具(如 RequireJS optimizer)来串联代码。有趣的是,使用了 Almond AMD shim,RequireJS 不需要在部署站点时打包,人们可能很容易认为脚本加载器可以轻松地转移到开发之外。

也就是说,James Burke 可能会说在页面加载完成后再动态加载脚本仍有它的使用场景,RequireJS 也可以这样用。有了这些概念在闹钟,我们就可以开始下面的学习了。