npm 包

Angular应用程序以及Angular本身都依赖于很多第三方包(包括Angular自己)提供的特性和功能。 这些包由Node包管理器(npm)负责安装和维护。

Node.js和npm是做Angular开发的基础。

如果你的电脑上还没有装过,请立即获取它

通过在终端/控制台窗口中运行node -vnpm -v命令,来验证下你是否正在使用node v4.x.x和npm 3.x.x。 过老的版本有可能出现问题。

我们建议使用nvm来管理node和npm的多个版本。如果你机器上已经有某些项目运行了node和npm的其它版本,你就会需要nvm了。

我们在搭建本地开发环境一章中安装并解释了package.json文件的 dependenciesdevDependencies区中指定了一组适用于新手的综合依赖包。

你当然可以使用其它包,不过这一组可以很好的协同工作,而且包含了我们在个系列文档中构建和运行范例应用时所需的一切。

注意:烹饪宝典或开发指南中的页面可能需要其它库,比如jQuery

它们远远超过了我们将在“快速起步”中所需要用到的。 实际上,它比我们在大多数应用中需要的还多。 安装的包比我们实际需要的包多,其实并没有什么坏处。 我们最终只会往客户端发送程序中实际用到的那些包。

本页面会解释每一个包是干什么的,以后你就可以根据自己的喜好和经验,随意替换它们了。

dependenciesdevDependencies

package.json包含两组包:dependenciesdevDependencies

dependencies下的这些包是运行本应用的基础,而devDependencies下的只在开发此应用时才用得到。 通过为install命令添加--production参数,你在产品环境下安装时排除devDependencies下的包,就像这样:

npm install my-application --production

dependencies

应用程序的package.json文件中,dependencies区下有三类包:

特性包

@angular/core - 框架中关键的运行期部件,每一个应用都需要它。 包括所有的元数据装饰器:ComponentDirective,依赖注入系统,以及组件生命周期钩子。

@angular/common - 常用的那些由Angular开发组提供的服务、管道和指令。

@angular/compiler - Angular的模板编译器。 它会理解模板,并且把模板转化成代码,以供应用程序运行和渲染。 开发人员通常不会直接跟这个编译器打交道,而是通过platform-browser-dynamic或离线模板编译器间接使用它。

@angular/platform-browser - 与DOM和浏览器相关的每样东西,特别是帮助往DOM中渲染的那部分。 这个包还包含bootstrapStatic方法,用来引导那些在产品构建时需要离线预编译模板的应用程序。

@angular/platform-browser-dynamic - 为应用程序提供一些提供商bootstrap方法,以便在客户端编译模板。不要用于离线编译。 我们使用这个包在开发期间引导应用,以及引导plunker中的范例。

@angular/http - Angular的HTTP客户端。

@angular/router - 路由器。

@angular/upgrade - 一组用于升级AngularJS应用的工具。

system.js - 是一个动态的模块加载器, 与ES2015模块规范兼容。 还有很多其它选择,比如广受欢迎的webpack。 SystemJS被用在了我们的文档范例中。因为它能工作。

今后,应用程序很可能还会需要更多的包,比如HTML控件、主题、数据访问,以及其它多种工具。

填充(Polyfill)包

在应用程序的运行环境中,Angular需要某些填充库。 我们通过特定的npm包来安装这些填充库,Angular本身把它列在了package.json中的peerDependencies区。

但我们必须把它列在我们package.json文件的dependencies区。

查看下面的“为什么用peerDependencies?”,以了解这项需求的背景。

core-js - 为全局上下文(window)打的补丁,提供了ES2015(ES6)的很多基础特性。 我们也可以把它换成提供了相同内核API的其它填充库。 一旦所有的“主流浏览器”都实现了这些API,这个依赖就可以去掉了。

rxjs - 一个为可观察对象(Observable)规范提供的填充库,该规范已经提交给了 TC39委员会,以决定是否要在JavaScript语言中进行标准化。 开发人员应该能在兼容的版本中选择一个喜欢的rxjs版本,而不用等Angular升级。

zone.js - 一个为Zone规范提供的填充库,该规范已经提交给了 TC39委员会,以决定是否要在JavaScript语言中进行标准化。 开发人员应该能在兼容的版本中选择一个喜欢的zone.js版本,而不用等Angular升级。

其它辅助库

angular-in-memory-web-api - 一个Angular的支持库,它能模拟一个远端服务器的Web API,而不需要依赖一个真实的服务器或发起真实的HTTP调用。 对演示、文档范例和开发的早期阶段(那时候我们可能还没有服务器呢)非常有用。 请到Http客户端一章中了解更多知识。

bootstrap - bootstrap是一个广受欢迎的HTML和CSS框架,可用来设计响应式网络应用。 有些文档中的范例使用了bootstrap来强化它们的外观。

devDependencies

列在package.json文件中devDependencies区的包会帮助我们开发该应用程序。 我们不用把它们部署到产品环境的应用程序中 —— 虽然这样做也没什么坏处。

concurrently - 一个用来在OS/X、Windows和Linux操作系统上同时运行多个npm命令的工具 lite-server : A light-weight, static file server, by John Papa with excellent support for Angular apps that use routing.

lite-server - 一个轻量级、静态的服务器, 由John Papa开发和维护。对使用到路由的Angular程序提供了很好的支持。

typescript - TypeScript语言的服务器,包含了TypeScript编译器tsc

@types/* - “TypeScript定义”文件管理器。 要了解更多,请参见TypeScript配置页。

为什么使用peerDependencies

在“快速起步”的package.json文件中,并没有peerDependencies区。 但是Angular本身在它自己的 package.json 中有, 它对我们的应用程序有重要的影响。

它解释了为什么我们要在“快速起步”的package.json文件中加载这些填充库(polyfill)依赖包, 以及为什么我们在自己的应用中会需要它们。

然后是对平级依赖(peer dependencies)的简短解释。

每个包都依赖其它的包,比如我们的应用程序就依赖于Angular包。

两个包,“A”和“B”,可能依赖共同的第三个包“C”。 "A"和“B”可能都在它们的dependencies中列出了“C”。

如果“A”和“B”依赖于“C”的不同版本("C1"和“C2”)。npm包管理系统也能支持! 它会把“C1”安装到“A”的node_modules目录下给“A”用,把“C2”安装到“B”的node_modules目录下给“B”用。 现在,“A”和“B”都有了它们自己的一份“C”的复本,它们运行起来也互不干扰。

但是有一个问题。包“A”可能只需要“C1”出现就行,而实际上并不会直接调用它。 "A"可能只有当每个人都使用“C1”时才能正常工作。如果程序中的任何一个部分依赖了“C2”,它就会失败。

要想解决这个问题,“A”就需要把“C1”定义为它的平级依赖

dependenciespeerDependencies之间的区别大致是这样的:

dependency说:“我需要这东西对我是直接可用的。”

peerDependency说:“如果你想使用我,你得先确保这东西对你是可用的”

Angular就存在这个问题。 因此,Angular的package.json中指定了一系列平级依赖包, 把每个第三方包都固定在一个特定的版本上。

我们必须自己安装Angular的peerDependencies

npm安装那些在我们的dependencies区指定的包时, 它也会同时安装上在那些包dependencies区所指定的那些包。 这个安装过程是递归的。

但是在npm的第三版中,它不会安装列在peerDependencies区的那些包。

这意味着,当我们的应用程序安装Angular时,npm将不会自动安装列在Angular的peerDependencies区的那些包

幸运的是,npm会在下列情况下给我们警告:(a) 当任何平级依赖缺失时 或(b) 当应用程序或它的任何其它依赖安装了与平级依赖不同版本的包时。

这些警告可以避免因为版本不匹配而导致的意外错误。 它们让我们可以控制包和版本的解析过程。

我们的责任是,把所有平级依赖包都列在我们自己的devDependencies

peerDependencies的未来

Angular的填充库依赖只是一个给开发人员的建议或提示,以便它们知道Angular期望用什么。 它们不应该像现在一样是硬需求,但目前我们也不知道该如何把它们设置为可选的。

不过,有一个npm的新特性申请,叫做“可选的peerDependencies”,它将会允许我们更好的对这种关系建模。 一旦它被实现了,Angular将把所有填充库从peerDependencies区切换到optionalPeerDependencies去。