在我们日常的node开发中,我经常会依赖于这样或那样的第三方包,而本章就来讨论一下如何管理node项目中的依赖。
什么是NPM
npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等),它是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,比如下载和安装第三方包到本地、发布自己编写的软件包到NPM服务器等。
什么是依赖包
依赖包指的是NodeJS中所依赖的第三方模块的软件包,它有package.json来进行描述,利用npm install来进行安装。
依赖包管理的类别
npm 目前支持以下几类依赖包管理:
在package.json中他们一般是已如下的形态存在:
dependencies
dependencies是一个将依赖包列表的所有包名称映射成一个版本范围的简单对象。
它是最常用的依赖管理对象,可以称之为应用依赖,或者叫做业务依赖。也就是说,当开发者发布当前应用后正常执行时所依赖的包列表,并不包含测试用的包(如单元测试的karma)和其他开发工具类包(如代码检查的eslint)。
关于版本号范围的编写标准,我们有必要重温一下(以下例子来源于npm官网)
除此之外,值还可以是git地址,由于用的少这里就不展开了。
devDependencies
devDependencies是开发环境依赖对象,他的使用频率也很高。
如果有人正计划在程序中下载和使用你的模块时,那么他们很可能不希望也不需要下载并构建你使用的外部测试/文档框架。
在这种情况下,最好在devDependencies对象中映射这些附加项,如:构建类包→grunt、gulp;测试类包→mocha、karma;编译类包→coffee。
安装条件:当用户执行npm link命令,或者在该项目的根目录下执行npm install时会安装devDependencies中定义的包。
安装脚本:可以通过下面的脚本安装开发环境并更新package.json
举个例子:下面是npm官网给出的应用场景
prepare脚本会在publish脚本执行之前被执行,也就是在说,在你发布之前会利用coffee脚本把你用coffee写的代码编译为JavaScript。
如果有人再问你 npm --save-dev和npm --save的区别,相信你一定能回答上了
peerDependencies
peerDependencies可以被称为同等依赖,或者叫同伴依赖,他更多的应用于扩展插件的package.json中。
在某些情况下,你希望将你编写的模块基于另一个插件,而你想描述你的模块与该插件的兼容性,而又不一定要引用这个插件。这时peerDependencies正好派上了用场。值得注意的是,你的模块很可能暴露在一个特定的接口,并且可能在该插件的文档中被提到。
举个例子:(该例子来源于npm官网)
例子中,假设该包为tea-latte,它依赖于tea包。
正如你所见到的一样,tea-latte应该是tea的一个扩展插件,那么按照常理你在使用tea-latte的情况下你一定是已经依赖了tea的。
在npm1和npm2的情况下,会默认将tea安装,而在npm3的情况下,如果你在依赖tea-latte时,却没有依赖tea,那么npm会报错,提示你需要引入tea包。
bundleDependencies
这个用的不会太多,所以不想详细说了……
它还有一个别名,bundledDependencies,他的参数是一个数组,这个配置的作用如下:
对于下面这个包some-package来说
在你的项目中使用npm3安装了some-package之后,项目的node_modules的文件结构是下面的样子:
也就是说,bundleDependencies 的作用就是在用户安装了 package-a 之后,将 package-a 所声明的依赖包汇总到 package-a 自身的 node_modules 下,便于用户管理,如果 package-a 中没有配置 bundleDepencies,在安装了 package-a 的项目下 node_modules 就会长这样:
optionalDependencies
如果你的node项目依赖了一个包 package-optional,假如这个 package-optional 没有安装,你仍然想让程序正常执行,这个时候 optionalDependencies 就非常适合你这个需求,optionalDependencies 跟 dependencies 声明方式完全一致,而且一个依赖如果同时在 dependencies 和 optionalDependencies 中声明,option 还会覆盖 dependency 的声明。如果 package-optional 这个包是可选的,在代码中就可以这样写了:
结语
对于一个简单的、自己练手的项目,你当然可以把所有的依赖都写在dependencies里。
但是随着项目功能的复杂度,已经对于效率的不对追求,那么你是可以利用上面介绍的这几种依赖管理方式来进行优化的。