本篇npm教程将重点介绍Node Package Manager,即通常所说的NPM。NPM有两个主要功能。它是一个命令行工具,用于运行各种开发工具和脚本,此外还有一个第三方库的注册表。事实上,根据最后的统计,NPM有大约65万个可用的软件包!这意味着对于你试图解决的任何问题,你都可以使用NPM。这意味着对于你想用Node.js解决的任何问题,很可能已经有了一个免费的软件包,你可以在自己的项目中利用。当然,你可以在www.npmjs.com 上找到NPM。此外,如果你有一个想与社区分享的软件想法--你可以创建你自己的包并与世界分享。现在让我们多了解一下NPM。
什么是package.json文件?
在我们继续前进之前,你要确保你的系统上安装了npm。要检查这一点,你可以在命令行中输入类似npm -v 。你的版本可能与你在这里看到的不同,但只要那里有一个数字值,你就可能是好的。

当你在做这件事的时候,检查一下所安装的node的版本也是无妨的。你可以在命令行中用node -v 来做这个。

现在,我们要创建一个名为npm-tutorial 的新目录,然后我们可以像这里一样进入该目录。

现在我们准备创建一个package.json文件,并了解它是如何工作的。这是一个JSON文件,包含了关于我们项目的基本信息。所有的Node应用程序都会有这个package.json文件。为了创建你的package.json文件,继续运行npm init。

当我们运行npm-init命令时,程序会引导我们完成填写创建package.json文件所需的元数据的过程。我们看到包的名称、版本、描述、入口点、测试命令、git repo、关键词、作者、许可证,以及确认。一旦你经历了这个过程,你将有一个package.json文件,它可能看起来像这样。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC"
}
这里的重点是,在你添加任何节点包之前,你必须创建一个package.json文件。我们采取了上面的冗长路线,但如果你想直接创建文件并立即接受所有的默认值--你可以输入npm init --yes ,文件就会在瞬间为你完成。
如何安装一个Node模块
好了,我们有了package.json文件,让我们继续添加一些第三方的包到项目中。首先,让我们安装underscore JavaScript库。首先,你可以在它的npm页面上查看关于underscore的信息。它显示,要安装它,我们需要做的就是在终端输入npm i underscore 。让我们现在就去做。

太棒了。我们可以查看package.json文件,它已经被更新,以反映underscore库现在是我们项目的一个依赖项。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"underscore": "^1.9.0"
}
}
现在在后台,npm做了它的工作,下载了你安装的库的所有文件。我们也可以在node_modules文件夹中看到这一点。现在它有一个underscore文件夹,里面有我们需要的underscore js的文件。

值得注意的是,在underscore文件夹内,实际上还有一个package.json文件。事实上,你安装的每个第三方模块都会包含它自己的package.json文件--就像你自己的父应用程序有一个package.json文件一样。
使用已安装的模块
我们安装了第三方模块,现在让我们来使用它。要做到这一点,我们所要做的就是要求它进入我们的项目。在你的项目根部创建一个新的index.js文件,并添加这段代码。
const _ = require('underscore');
require函数采取以下步骤来包含一个包。
- 检查它是否是一个核心模块,如果是,就加载它。
- 检查是否有文件或文件夹被要求,如果有,则加载它。
- 检查命名的模块是否存在于node_modules中,如果是,则加载它。
这就是npm为你解决一个模块的方法。
所以我们需要测试一下underscore,看看它是否有效。在之前的教程中,我们了解了underscore中的every()函数如何在浏览器中工作。现在让我们把这些例子中的一个移植到Node.js中。在我们的index.js文件中。
const _ = require('underscore');
let people = [{
name: 'Jim',
mustache: true
},
{
name: 'Glenn',
mustache: true
},
{
name: 'Brian',
mustache: true
},
{
name: 'George',
mustache: ''
}
],
hasCropDuster = (value) => {
return (value.mustache !== '');
};
console.log('Do all people have a mustache?');
console.log(_.every(people, hasCropDuster));
我们可以运行该程序,看看它是否工作。在这种情况下,underscore将检查每个人是否有胡子。在这个例子中,并不是所有的人都有胡子,所以它应该显示为假。让我们来看看。

看起来它工作得很好!这验证了这个库实际上是我们项目的一部分,我们可以看到它正在做它应该做的工作。
模块可以有自己的依赖性
当安装一个第三方模块时,该包在安装过程中可能会安装它自己的一套依赖关系。让我们看看这句话是什么意思。我们可以通过输入npm i mongoose为我们的项目安装mongoose。

检查我们的package.json文件,可以看到mongoose作为一个依赖项的新条目。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mongoose": "^5.1.1",
"underscore": "^1.9.0"
}
}
现在,让我们列出node_modules的内容,看看里面有什么。

哇!那里有很多新的文件夹。我们所做的就是安装mongoose包,那么发生了什么?嗯,事实证明,mongoose包实际上需要很多其他的软件包才能完成它的工作。因此,当mongoose被安装时,npm会自动安装该软件包的所有依赖项。很温馨吧?我知道,如果你不得不手工安装所有这些依赖项,你会把它弄糟的。我知道我会的。
NPM包和源代码控制
如果你建立了一个项目,并打算在Github或其他类型的源控制机制上分享它,你永远不会包括node_modules文件夹。这是因为随着应用程序的增长,你可能会看到node_modules文件夹膨胀到数百兆字节的大小。如果你在源码控制中包括这个,任何时候其他开发者想要检查你的项目--他们将等待node_modules文件夹的下载。这不是一个好的做法。然而,这并不是一个问题,因为package.json文件包含了项目所需的所有依赖项。因此,如果另一个开发人员检查你的代码,他们所要做的就是运行npm install ,npm将下载并安装任何数量的所需的依赖项到他们机器上的node_modules。下面是一个关于如何排除node_modules的例子。首先我们初始化一个git repo。

然后,我们添加一个.gitignore文件,并指定我们不希望包括node_modules文件夹。

现在当我们再次运行git status ,node_modules文件夹不再被跟踪和提交。

我们可以继续添加这些文件,并且也可以提交它们。
npm-tutorial $git add .
npm-tutorial $git commit -m "First commit!"
[master (root-commit) f65e415] First commit!
4 files changed, 193 insertions(+)
create mode 100644 .gitignore
create mode 100644 index.js
create mode 100644 package-lock.json
create mode 100644 package.json
SemVer(语义版本管理)
让我们再仔细看看package.json中我们的依赖项的版本。
"dependencies": {
"mongoose": "^5.1.1",
"underscore": "^1.9.0"
}
请注意,我们目前安装的是mongoose和underscore。每个版本都以一个^ 或 caret 符号开头。这是什么意思?那么在node包中,有三个组成部分。它的格式是X.Y.Z,X代表主要版本。Y代表次要版本。Z代表补丁版本。这就是所谓的SemVer或Semantic Versioning。回到那个圆点字符。这表明,依赖关系应该使用这个主要版本。因此,在我们上面的例子中,当依赖关系被安装时,我们想要最新的版本或mongoose,只要它是5个主要版本的一部分。同样地,我们对underscore感兴趣,它的主要版本是1。换句话说,Major版本必须是5或1,然而如果有较新的minor和patch版本,我们也会接受。这一点很重要。
列出已安装的软件包
为了查看该项目使用了哪些已安装的依赖项,我们可以简单地使用list命令。

这将列出项目中的所有依赖项,以及每个依赖项的依赖性。也许你只想看看你的实际项目所依赖的东西,而不是整个依赖树。对于这一点,只需使用深度标志设置为0。

查看软件包的注册表信息
你可能想了解你正在使用的npm包的更多信息。要做到这一点,你可以访问npm网站并阅读关于该包的信息。然而,你可以在终端中获得很多关于该包的有用信息。例如,让我们在终端输入npm view mongoose 。

哇!这是一个很大的信息。这是很好的信息。我们可以看到几乎所有我们需要知道的关于该包的信息。让我们也来学习更多关于underscore的知识。

卸载一个包
当然,有时你可能想从你的应用程序中删除一个包。让我们继续前进,从我们的项目中删除underscore。

就这样,underscore现在已经从我们的项目中删除了。如果我们再一次检查package.json文件,我们会看到它也从依赖关系区域中被删除。在这一点上,只有mongoose作为第三方软件包被安装。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mongoose": "^5.1.1"
}
}
安装一个特定版本的软件包
有时也可能需要一个特定版本的库,以确保它在一个特定的项目中工作。比方说,我们的项目实际上需要underscore的1.8.3版本而不是1.9.0版本。我们可以像这样指定要安装哪个版本。

就这样,你就有了你需要的特定版本。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mongoose": "^5.1.1",
"underscore": "^1.8.3"
}
}
更新一个npm包
实际上,如果你在你的项目中使用最新的软件包可能是最好的。首先,你应该用npm outdated 命令检查是否有什么东西已经过时了。有了这个,npm就可以很容易地确定你的任何包是否需要更新。

现在我们可以运行npm update ,再次更新underscore。

注意:运行npm update 命令将只更新package.json中列出的任何东西的次要版本和补丁版本。主要版本将不会被更新。如果你需要改变主要版本,你可以使用npm-check-updates。
关于DevDependencies?
到目前为止,我们已经看到了如何在我们的项目中使用依赖关系。换句话说,我们的应用程序将需要这些包才能正常运行。有的时候,我们在开发过程中只需要某些包。这通常是在做测试驱动开发或一些类似的应用时。让我们继续安装Mocha测试包,作为开发的唯一依赖。我们可以通过在命令行中输入npm i mocha --save-dev 。

这将为我们安装Mocha,如果我们检查package.json文件,我们可以看到我们在devDependencies部分有一个新的包。
{
"name": "npm-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mongoose": "^5.1.1",
"underscore": "^1.9.0"
},
"devDependencies": {
"mocha": "^5.2.0"
}
}
这指定了mocha在构建和测试应用程序时被包含,但在生产环境中不应该被包含。
npm小抄
这里有一些命令可以作为快速参考。
- npm i
<packageName>安装一个软件包 - npm i
<packageName>@<version>安装一个软件包的特定版本 - npm i
<packageName>-save-dev安装一个作为开发依赖的软件包 - npm un
<packageName>卸载一个软件包 - npm list -depth=0列出已安装的软件包
- npmoutdated查看过时的软件包
- npm update更新软件包
- 要全局安装/卸载软件包,请使用 -
g标志。
Node包管理器教程总结
在这个npm教程中,我们了解到每个Node应用程序都有一个package.json文件,其中包括关于该项目的元数据。应用程序的名称、版本、依赖性和其他信息是元数据的一部分。我们可以利用NPM从NPM注册表中下载并安装第三方软件包。当我们这样做时,这些已安装的包和它们的依赖关系将被存储在node_modules文件夹中。Node包遵循major.minor.patch的语义版本惯例。