NPM指南
文章目录

npm 全称:Node Package Manager (Node 包管理器),目前是Web前端开发重要依赖工具之一。安装Node.js默认会安装npm,前端各种资源都可以通过一个npm命令下载到自己的本地计算机上。
用户通过一个命令将npm上发布的包下载自己本地计算机并在项目中使用,也可以将自己的包发布到npm上供全球Web前端开发者下载使用。
npm的出现极大提升了前端开发体验。
npm 命令
npm help
1 | npm help <command> |
通过该命令可以帮助我们快速查看具体npm命令的用途。
npm help -l可以查看所有所有npm命令
npm init
npm包必须有个 package.json文件,通过npm init可以让自动在目录下创建一个package.json文件,命令行会弹出几个问题用于填充package.json。如果你想快速跳过可以使用npm init -y命令。
npm install
npm install用于将依赖的包下载到本地node_modules目录中
npm install <package name>可以是注册在npm服务上的包,也可以是Github上一个具体项目地址。
1 | $ npm install express |
npm安装的包会记录在package.json文件中。
package.json文件有两种记录安装包的方式:生产依赖(dependencies)和开发依赖(devDependencies)。
1 | "dependencies": { |
1 | "devDependencies": { |
npm install <packagename>安装默认是生产依赖,也可以使用npm install -save <packagename>或npm install -S <packagename>
开发依赖的安装命令是:npm install -save-dev <packagename>或npm install -D <packagename>
npm ci
npm ci功能和npm install命令作用一样,它比npm install安装更快,因为它会跳过一些面向用户的操作,它的安装比npm install更严格,它可以帮助捕获由大多数npm用户的增量安装的本地环境引起的错误或不一致。
npm ci和npm install区别有:
- 安装前目录必须存在
package-lock.json或npm-shrinkwrap.json。 - 如果
package-lock.json包中锁定的包版本和package.json中包版本不一致,则npm ci将提示错误并提示错误。 npm ci只能整项目依赖包的安装,不能安装单个依赖包。- 如果
node_modules目录存在,在npm ci安装前会移除node_modules目录。 - 它不会对
package.json和任何锁定包版本的文件进行操作。
npm ci一般在自动话环境中使用,例如:测试平台,持续化集成,部署。
npm update
npm update用于更新本地依赖包。它会先查询远程服务器最新包的版本,再与本地版本进行比较,如果远程版本更新并符合本地版本安装规,它就将本地依赖包更新到最新版本。
npm update更新时,添加参数-S或-D。它会将package.json中的版本号更新。
npm dist-tag
npm dist-tag是管理包标签指令
1 | $ npm dist-tag add <pkg>@<version> [<tag>] |
add:使用给指定的包版本设定标签rm:将包中不需要的标签移除ls:将包的所有标签展示出来
在安装包时,可以通过设定标签名称下载指定版本的包
1 | $ npm install <name>@<tag> |
npm config
npm config命令用于管理npm包管理文件
1 | $ npm config set <key> <value> [-g|--global] |
用的最多的npm config命令是npm config set registry https://registry.npm.taobao.org
npm version
你还在手动更新package.json中的版本号嘛?现在一个npm version xxx命令就可以搞定了。它会将你设置的版本号写入package.json文件中。
npm包版本号的规则是:重大版本号.功能版本号.修复优化版本号
npm outdated
此命令将检查注册表,查看是否有安装的包已过时
1 | npm outdated [[<@scope>/]<pkg> ...] |
如果不指定pkg,则检查所有过期的包;若指定pkg,则检查指定的pkg。\
- wanted 显示符合semver规范的最大版本号。若没有多余版本号,则显示当前版本。
- latest 显示注册表中被标记为latest的版本。默认情况下latest标记表示最新版本,特殊情况下不是,这取决于开发人员的包管理制度。
- location 显示包在依赖关系树中的位置。请注意,npm outdated默认depth为0,仅看到过期包的顶级依赖项。
- package 显示包名。若使用了(–long/-l)则还是显示这个包属于dependencies还是devDependency。
1 | npm outdated --depth=1 // 显示依赖关系树最大深度,默认是 0 |
npm ls
用于查询工程或全局已安装的npm包依赖树。
可以设定 包名查看 安装情况。
1 | npm ls [[<@scope>/]<pkg> ...] |
可以通过--depth n指定层级
npm view
打印指定包的信息.
1 | npm view [<@scope>/]<name>[@<version>] [<field>[.<subfield>]...] |
package.json
每个npm包根目录下都会有一个package.json文件,该文件含有包的所有重要信息,例如:包名,版本号,许可协议等。
name
name表示该项目的名称,它的命名规则是限制的:
- 名称长度必须小于214个字节
- 不能以
.和_下划线开头 - 不能包含大些字母
name会成为URL的一部分,所以不能包含非法的URL字符
npm官方给了一些命名的建议:
- 不要使用和node.js模块相同的名称
- 名称中主要包含
js,node字符串 - 名称也许会被写入require参数中,所以最好取个简单有意义的名称
- 创建一个名称前先到https://www.npmjs.com/查询下该名称是否已经被使用
version
如果你计划发布你的npm包,你必须要确保在package.json文件中定义了name和version字段。
name和package字段是包的唯一性标志,包的区分就是依靠name和package字段。
version字段定义当前包的版本号,版本号的命名规则是:重大版本号.功能版本号.修复优化版本号
发布稳定版本
1 | # 更新版本号(major | minor | patch | premajor | preminor | prepatch | prerelease) |
预发布版本
1 | # 发布一个 prelease 版本,tag=beta |
description
description字段描述包的一些信息,可以方便用户通过npm search搜索到你的npm包
homepage
homepage字段声明包的主页地址
license
license字段定义你的包使用的许可证,不同的许可证定义了你的包使用范围和用途。https://spdx.org/licenses/可以看到所有许可证和它的详细说明
main
main定义了包入口的文件,通过require()引入你的包时,包管理器会将main中定义的文件引入进去。main默认入口文件名是index.js
dependencies
dependencies字段用于定义项目运行所依赖的库。它定义为一个对象,key表示包名称,value是包的版本号。
依赖包的版本号定义有四种形式:
- 指定固定的版本:
1.2.0 - 波浪号+指定版本号:
~1.2.0它表示安装1.2.x最新的版本,不低于1.2.0,但不安装1.3.0。安装时不改变大版本号和次要版本号 - 插入号+指定版本包:
^1.2.0,它表示安装1.x.x最新的版本,不安装2.x.x版本,也就是不改变大版本号。但是如果大版本号是0,则它的意义和波浪号一样,它不改变次版本号。因为大版本号是0说明该包还只是测试简单。 latest: 安装最新的版本
devDependencies
devDependencies字段定义开发是依赖的包,它表示项目运行时并不依赖的包。
peerDependencies
1 | 如果你安装我,那么你最好也安装X,Y和Z. |
有时候做一些插件开发,比如grunt等工具的插件,它们往往是在grunt的某个版本的基础上开发的,而在他们的代码中并不会出现require(“grunt”)这样的依赖,dependencies配置里边也不会写上grunt的依赖,为了说明此模块只能作为插件跑在宿主的某个版本范围下,可以配置peerDependencies:
1 | { |
上面这个配置确保再npm install的时候tea-latte会和2.x版本的tea一起安装,而且它们两个的依赖关系是同级的:
├── tea-latte@1.3.5
└── tea@2.2.0
这个配置的目的是让npm知道,如果要使用此插件模块,请确保在宿主环境按照了我需要的依赖包(peerDependencies中声明的包)。
即使宿主环境并没有使用该依赖包,但还是会在它的node_modules中按照该依赖包.
npm2和npm3中peerDependencies的区别
正如上一节谈论的,在npm2中,PackageA包中peerDependencies所指定的依赖会随着npm install PackageA一起被强制安装,所以不需要在宿主环境的package.json文件中指定对PackageA中peerDependencies内容的依赖。
但是在npm3中,peerDependencies的表现与npm2不同:
npm3中不会再要求peerDependencies所指定的依赖包被强制安装,相反npm3会在安装结束后检查本次安装是否正确,如果不正确会给用户打印警告提示。
就拿上面的例子来说,如果我们npm install PackageA安装PackageA时,你会得到一个警告提示说:
PackageB是一个需要的依赖,但是没有被安装。
这时,你需要手动的在MyProject项目的package.json文件指定PackageB的依赖。
另外,在npm3的项目中,可能存在一个问题就是你所依赖的一个package包更新了它peerDependencies的版本,那么你可能也需要在项目的package.json文件中手动更新到正确的版本。
bundledDependencies
上面的单词少个d,写成bundleDependencies也可以。
指定发布的时候会被一起打包的模块。
optionalDependencies
如果一个依赖模块可以被使用, 同时你也希望在该模块找不到或无法获取时npm继续运行,你可以把这个模块依赖放到optionalDependencies配置中。这个配置的写法和dependencies的写法一样,不同的是这里边写的模块安装失败不会导致npm install失败。
1 | try { |
optionalDependencies 中的配置会覆盖dependencies中的配置,最好只在一个地方写。
config
用来设置一些项目不怎么变化的项目配置,例如port等。
用户用的时候可以使用如下用法:
1 | http.createServer(...).listen(process.env.npm_package_config_port) |
可以通过npm config set foo:port 80来修改config
1 | { |
npx
npx用于执行npm包的二进制脚本。
npx <command>它会查找node_modules/.bin目录对于的可执行二进制脚本。如果本地没有对于的可执行二进制脚本,它会去全局查找。如果全局也没有,它就会从远程仓库下载对应的npm包。
1 | $ npm i -D webpack |
npm5.2.0版本之后会默认安装npx包。
有了npx,对于需要执行的npm包二进制命令,你不用将它写进scripts或进行全局安装。
发布npm包
将包发布到npm远程仓库非常简单,只需要三个步骤(确保你的包准备好了)。
npm adduser注册一个npmjs.com的账号npm login登录已有的账号npm publish发布包(在包的根目录执行)
注意: 在发布前,你应该登录https://www.npmjs.com 看下自己的包名是否已经存在。
如果你的registry指向其它镜像,你需要将它设定为https://registry.npmjs.com/
一个完整的npm包,应该包括:
package.json文件README.md文件,说明包的用途和使用方式index.js文件,包的入口文件tests目录,单元测试文件目录
作者: Fynn
链接: https://fynn90.github.io/2018/11/18/npm%E6%8C%87%E5%8D%97/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可