npm使用说明
介绍 npm
的使用。
npm简介
npm
有两层含义。一层含义是Node
的开放式模块登记和管理系统,网址为npmjs.org
。另一层含义是Node
默认的模块管理器,是一个命令行下的软件,用来安装和管理Node
模块。
npm
不需要单独安装。在安装Node
的时候,会连带一起安装npm
。但是,Node
附带的npm
可能不是最新版本,使用下方命令查看npm
的版本。
1 | $ npm -v |
如果不是最新的,最好用下面的命令,更新到最新版本:
1 | $ npm install npm@latest -g |
基本命令
npm list
npm list
列出项目的依赖信息。也可以使用 npm ls
简写命令。
1 | # 列出当前项目的说有依赖项 |
npm init
使用npm init
初始化包。即初始化 package.json
文件。
1 | # 会有一系列提问设置,根据提问设置package.json文件中的基本字段内容 |
我们可以为 init
命令初始化一些值,如:
1 | > npm set init.author.email "yisiwings@163.com" |
npm install
Node
模块采用npm install
命令安装。
每个模块可以“全局安装”,也可以“本地安装”。“全局安装”指的是将一个模块安装到系统目录中,各个项目都可以调用。一般来说,全局安装只适用于工具模块,比如eslint
和@vue/cli
。“本地安装”指的是将一个模块下载到当前项目的node_modules
子目录,然后只有在项目目录之中,才能调用这个模块。
1 | # 本地安装 |
安装之前,npm install
会先检查,node_modules
目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也是如此。
如果你希望,一个模块不管是否安装过,npm
都要强制重新安装,可以使用-f
或--force
参数。
1 | $ npm install <package name> --force |
如果你希望,所有模块都要强制重新安装,那就删除node_modules
目录,重新执行npm install
。
1 | $ rm -rf node_modules |
install
命令总是安装模块的最新版本,如果要安装模块的特定版本,可以在模块名后面加上@
和版本号
。
1 | $ npm install sax@latest |
如果使用--save-exact
参数,会在package.json
文件指定安装模块的确切版本。
1 | $ npm install readable-stream --save --save-exact |
install
命令可以使用不同参数,指定所安装的模块属于哪一种性质的依赖关系,即出现在packages.json
文件的哪一项中。
–save:模块名将被添加到dependencies,可以简化为参数-S。
–save-dev: 模块名将被添加到devDependencies,可以简化为参数-D。
1 | $ npm install sax --save |
npm install
默认会安装dependencies
字段和devDependencies
字段中的所有模块,如果使用--production
参数,可以只安装dependencies
字段的模块。
1 | $ npm install --production |
如果你的网速很慢,建议使用淘宝镜像代理。安装完后,你就可以使用
cnpm
代替npm
命令。npm
特有的一些命令除外,比如:npm adduser
、npm login
、npm publish
等等。
1 | # 安装cnpm 命令行工具 ,使用淘宝的npm 镜像 |
npm update
npm update
命令可以更新本地安装的模块。
1 | # 升级当前项目的指定模块或所有可以更新的模块 |
它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装。在升级包时,npm
会根据 package.json
文件中定义的 语义化版本规则
判断应该更新安装哪个版本的包。使用
npm outdated
命令可以准确查看通过 语义化版本规则
计算出来的版本号(Wanted字段)。
执行更新命令后 package.json
里面模块的版本号变化:
1 | // 更新之前的package.json |
:warning: 注意,从
npm v2.6.1
开始,npm update
只更新顶层模块,而不更新依赖的依赖,以前版本是递归更新的。如果想取到老版本的效果,要使用下面的命令:
1 | $ npm --depth 9999 update |
npm uninstall
npm uninstall
命令,卸载已安装的模块。
1 | # 卸载指定的本地模块 |
npm run
npm
不仅可以用于模块管理,还可以用于执行脚本。package.json
文件有一个scripts
字段,可以用于指定脚本命令,供npm
直接调用。
1 | { |
其他命令
npm link
npm link
命令可以将某个模块关联安装到 nodejs
全局环境中,以便可以在本机的任何项目中引用她。
比如,我们在构建自己的模块的时候,我们需要对其进行测试,在没有发布到 npmjs
上之前,我们无法使用如下命令来安装她:
1 | npm install my-module |
这时,npm link
就可以派上用场了,我们 cd
进入到 my-module
项目所在根目录后,打开终端命令行,键入:
1 | npm link |
此时,my-module
模块的副本已经被关联并安装到 nodejs
的全局环境中。
1 | $ E:\nodejs\node_modules\my-module -> C:\Users\yisiw\Desktop\my-module |
当要使用 my-module
模块时,可以直接在项目内命令行中输入:
1 | npm link my-module |
my-module
模块就会被安装在 node_mnodules
文件夹中,此时,你就可以使用导入语法导入她了
1 | const foo = require('my-module') |
这在编写自己的模块,需要测试的时候尤其有用。
npm home,npm repo
npm home
命令可以打开一个模块的主页,npm repo
命令则是打开一个模块的代码仓库。
1 | $ npm home <package name> |
这两个命令不需要模块先安装。
npm outdated
npm outdated
命令检查当前项目所依赖的模块,是否已经有新版本。
1 | $ npm outdated |
它会输出当前版本(current version)、应当安装的版本(wanted version)和最新发布的版本(latest version)。
注:(wanted version) 是根据 package.json 文件中的依赖字段申明的
语义化版本规则
推算出来的。详见下方的语义化版本规则
查看说明。
npm prune
npm prune
检查当前项目的node_modules
目录中,是否有package.json里面没有提到的模块,然后将所有这些模块输出在命令行。
1 | $ npm prune |
npm shrinkwrap
npm shrinkwrap
的作用是锁定当前项目的依赖模块的版本。
1 | $ npm shrinkwrap |
运行该命令后,会在当前项目的根目录下生成一个npm-shrinkwrap.json
文件,内容是node_modules
目录下所有已经安装的模块,以及它们的精确版本。
下次运行npm install
命令时,npm
发现当前目录下有npm-shrinkwrap.json
文件,就会只安装里面提到的模块,且版本也会保持一致。
npm owner
模块的维护者可以发布新版本。npm owner
命令用于管理模块的维护者。
1 | # 列出指定模块的维护者 |
npm deprecate
如果想废弃某个版本的模块,可以使用npm deprecate
命令。
1 | $ npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3" |
运行上面的命令以后,小于0.2.3版本的模块的package.json都会写入一行警告,用户安装这些版本时,这行警告就会在命令行显示。
npm adduser
npm adduser
用于在npmjs.com
注册一个用户。
1 | $ npm adduser |
npm login
用于登陆npm
。
1 | $ npm login |
npm publish
登陆过后可以使用 npm publish
发布一个版本。
1 | $ npm publish |
如果当前模块是一个beta版,比如1.3.1-beta.3,那么发布的时候需要使用tag参数,将其发布到指定标签,默认的发布标签是latest。
1 | $ npm publish --tag beta |
package.json文件
每个项目的根目录下面,一般都有一个package.json
文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install
命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。
package.json
文件至少要有两部分内容:
- name
全部小写,没有空格,可以使用下划线或者横线。
- version
x.x.x 的格式,符合语义化版本规则
。
例:
1 | { |
其他内容:
description:描述信息,有助于搜索
main: 入口文件,一般都是 index.js
scripts:支持的脚本,默认是一个空的 test
keywords:关键字,有助于在人们使用 npm search 搜索时发现你的项目
author:作者信息
license:默认是 MIT
bugs:当前项目的一些错误信息,如果有的话
dependencies:项目生产过程中的依赖包
devDependencies:项目开发、测试过程中的依赖包
homepage: 该包的项目主页地址
例:
1 | { |
语义化版本规则
dependencies
或 devDependencies
的内容,以 "vue": "^2.5.17"
为例,我们知道 key
是依赖的包名称,value
是这个包的版本。那版本前面的^
、~
或者版本直接是一个 *
是什么意思呢?
这就是 npm
的 Semantic versioning
,简称 Semver
,中文含义即语义化版本规则。这些特殊符号被称作 semver 通配符
。
在开发中我们有过这样的经验:有时候依赖的包升级后大改版,之前提供的接口不见了,这对使用者的项目可能造成极大的影响。
因此我们在声明对某个包的依赖时需要指明是否允许 update
到新版本,什么情况下允许更新,npm
包提供者需要了解的 Semantic versioning 语义化版本规则。版本由三部分组成:X,Y,Z,分别是主要版本,次要版本和补丁版本。
作为包的开发者,应该从 1.0.0 版本开始。以后要升级版本应该遵循以下标准:
- 补丁版本:解决了
Bug
或者一些较小的更改,增加最后一位数字,比如1.0.1
- 小版本:增加了新特性,同时不会影响之前的版本,增加中间一位数字,比如
1.1.0
- 大版本:大改版,无法兼容之前的,增加第一位数字,比如
2.0.0
作为包的使用者,可以针对自己的需要填写依赖包的版本规则:
作为使用者,我们可以在 package.json
文件中写明我们可以接受这个包的更新程度(假设当前依赖的是 1.0.4 版本):
如果不打算更新任何版本,也就是只使用固定版本的包,可以这么写:
- 1.0.4
如果只打算接受补丁版本的更新(也就是最后一位的改变),就可以这么写:
1.0
1.0.x
~1.0.4
如果接受小版本的更新(第二位的改变),就可以这么写:
1
1.x
^1.0.4
如果可以接受大版本的更新(自然接受小版本和补丁版本的改变),就可以这么写:
x
package-lock.json文件
背景
在 package.json
中定义这样的依赖项的真正好处是,任何有权访问 package.json
的人都可以创建一个包含运行应用程序所需模块的依赖项文件夹,但是让我们来看看事情可能出错的具体方式。
假设我们创建了一个将使用 vue
的新项目。我们安装了 vue
:
1 | $ npm install vue --save |
在安装时,vue
的最新版本是2.5.17
,所以 “vue”:“^2.5.17”
作为我的package.json
中的依赖项添加,并且我的电脑安装了确切的版本。
现在也许明天,vue
的维护者会发布 bug
修复或新特性的添加,发布后的最新版本变为2.6.0
。 显然,根据版本号的变化,我们知道,这是新增了新的特性了,vue
的这个版本添加 v-slot
指令,用于逐步替换掉 2.5.x
版本的 slot-scope
特性,并且计划在 3.x
版本完全去除 slot-scope
特性。
然后,如果有人想要为我的项目做贡献,他们会克隆它,然后运行npm install
。因 2.6.0
是具有相同主要版本的更高版本,所以为它们安装。 我们都安装 vue
,但我们却是不同的版本。
从理论上讲,它们应该仍然是兼容的,但也许 bugfix 会影响我们正在使用的功能,而且当使用vue
版本2.5.17
和2.6.0
运行时,我们的应用程序可能会产生不同的结果。(虽然 vue
的这次版本更新兼顾到了 2.5.x
的版本,你依然可以使用 slot-scope
特性,但其他库可就不一定了)。
目的
package-lock.json
的目的是避免上述情况,其中从同一 package.json
安装模块会导致两种不同的安装。 在 npm
版本 5.x.x
中添加了 package-lock.json
,因此如果你使用的是主要版本 5
或更高版本,除非禁用它,否则它会自动生成。
内容结构
package-lock.json
是package.json
中列出的每个依赖项的大型列表,应安装的特定版本,模块的位置(URI),验证模块完整性的哈希,它需要的包列表 ,以及依赖项列表。 让我们来看看 vue
的列表是什么:
1 | "vue": { |
npm(^5.x.x)
之后的做法,npm
使用package-lock.json
,而不是使用package.json
来解析和安装模块。也就是说,当你使用 npm install
安装所有项目依赖时,npm
会根据 package-lock.json
文件中各模块包的 version
字段来安装特定版本的依赖包。
因为 package-lock.json
为每个模块及其每个依赖项指定了版本,位置和完整性哈希,所以它每次创建的安装都是相同的。 无论你使用什么设备,或者将来安装它都无关紧要,每次都应该给你相同的结果,这非常有用。
如果我们想要更新 vue
的版本怎么办呢?常规操作是:
npm outdated vue
查看vue
的最新变动。
1 | $ npm outdated vue |
可以看出,vue
的最新版本变为 2.6.9
了。于是我们可以使用 npm update
命令来更新 vue
。
1 | $ npm update vue |
现在 package-lock.json
文件中 vue
的变化。
1 | "vue": { |
没错!她现在已经被锁定为 2.6.9
的版本了。此时,你应该将你的 package-lock.json
和 package.json
变更提交到代码控制仓库,这时,当你的同事 pull
代码的时候,发现这两个文件发生了变化,那么他应该重新执行 npm install
,已确保他项目的 node_modules
中的所有依赖与其他开发人员一致。
能够触发
package-lock.json
文件变更的操作。
- 手动修改
package.json
中依赖包的版本号,然后执行npm install
(不推荐)。 - 使用
npm update [package name[@version]]
来更新包。(推荐)