npm 是什么
npm是随同NodeJS一起安装的包管理工具。
常见使用场景:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
发布npm包
一、安装npm(新版的NodeJS已经集成了npm,所以安装的时候npm也一并安装好了)
二、注册npm账号,注册完会收到邮件,需要点击验证一下,不然不能上传包
三、新建一个文件夹npm-study-qhw,打开命令行,输入
1 | npm init --yes |
npm init 是执行默认行为,输出一个初始化的 package.json 文件, 添加–yes参数(或-y),则生成一个默认的配置文件

要补全一下author
四、新建index.js文件

五、添加用户
1 | npm adduser |
六、发布
1 | npm publish |
遇到报错如下:

因为使用的是淘宝源,需要切换到npmjs的网址
1 | npm config set registry http://registry.npmjs.org/ |
之后再发布一次

七、查看与安装

新建另外一个文件夹
1 | 新增package.json文件 |

npm install packageName的时候,会自动添加到dependencies下面(与npm版本有关)。

八、更新版本
1 | npm version <update_type> |
九、删除
强制删除,不要占用npm包名
1 | npm unpublish -f |
常见命令
1 | 查看npm版本 |
npm link使用
项目A和项目B,B依赖A
在本地调试的时候,在项目A目录下,创建软链
1 | npm link |
在项目B目录下
1 | npm link A |
这里的A和B分别对应项目package.json文件里的name字段(取名当然不能为A和B)
package.json文件
name:包名,全部小写,没有空格,可以使用下划线或者横线
version:版本号
npm采用了semver规范作为依赖版本管理方案。
按照semver的约定,一个npm依赖包的版本格式一般为:主版本号.次版本号.修订号(x.y.z),每个号的含义是:
主版本号(也叫大版本,major version)
大版本的改动很可能是一次颠覆性的改动,也就意味着可能存在与低版本不兼容的API或者用法,(比如 vue 2 -> 3)。
次版本号(也叫小版本,minor version)
小版本的改动应当兼容同一个大版本内的API和用法,因此应该让开发者无感。所以我们通常只说大版本号,很少会精确到小版本号。
修订号(也叫补丁,patch)
一般用于修复bug或者很细微的变更,也需要保持向前兼容。
常见版本号格式:
“1.2.3”:精确版本号。
“^1.2.3”:兼容小版本和补丁更新的版本号,大版本号为 0 版本号的时候处理机制不同
1 | "^1.2.3" 等价于 ">= 1.2.3 < 2.0.0"。即只要最左侧的 "1" 不变,其他都可以改变。所以 "1.2.4", "1.3.0" 都可以兼容。 |
“~1.2.3”:表示只兼容补丁更新的版本号。关于 ~ 的定义分为两部分:如果列出了小版本号(第二位),则只兼容补丁(第三位)的修改;如果没有列出小版本号,则兼容第二和第三位的修改。
1 | "~1.2.3" 列出了小版本号 "2",因此只兼容第三位的修改,等价于 ">= 1.2.3 < 1.3.0"。 |
“1.x” 、”1.X”、1.*“、”1”、”*“:表示使用通配符的版本号。x、X、* 和 (空) 的含义相同,都表示可以匹配任何内容
1 | "*" 、"x" 或者 (空) 表示可以匹配任何版本。 |
description:描述信息,有助于搜索
main: 入口文件,一般都是 index.js
keywords:关键字,有助于在人们使用 npm search 搜索时发现你的项目
author:作者信息
scripts:用于定义脚本命令
dependencies:业务依赖
这种依赖在项目最终上线或者发布npm包时所需要, 通过npm install/i packageName -S/—save,把包装在依赖项里,如果没有没有指定版本,则安装npm仓库中最新版本的包,可以把版本号写在包名最后来指定版本npm i vue@3.0.1 -S。
从npm 5.x开始,可以不用手动添加-S/--save指令,直接执行npm i packageName把依赖包添加到dependencies中去。
devDependencies:开发依赖
这种依赖只在项目开发时所需要,即其中的依赖项不应该属于线上代码的一部分。比如构建工具webpack、gulp,预处理器babel-loader、scss-loader,测试工具e2e、chai等,这些都是辅助开发的工具包,无须在生产环境使用。通过npm install/i packageName -D/--save-dev安装。
并不是只有在dependencies中的模块才会被一起打包,而在devDependencies中的不会!模块能否被打包,取决于项目里是否被引入了该模块! 在业务项目中dependencies和devDependencies没有什么本质区别,只是单纯的一个规范作用,在执行npm i时两个依赖下的模块都会被下载;而在发布npm包的时候,包中的dependencies依赖项在安装该包的时候会被一起下载,devDependencies依赖项则不会。
peerDependencies:同伴依赖
这种依赖的作用是提示宿主环境去安装插件在peerDependencies中所指定依赖的包,然后插件所依赖的包永远都是宿主环境统一安装的npm包,最终解决插件与所依赖包不一致的问题。
比如:`element-ui@2.6.3只是提供一套基于vue的ui组件库,但它要求宿主环境需要安装指定的vue版本,所以你可以看到element项目中的package.json`中具有一项配置:
1 | "peerDependencies": { |
反正就是安装了一个包,要按照它的需要,去安装别的包。
bundledDependencies / bundleDependencies:打包依赖
optionalDependencies:可选依赖
npm对node_modules的处理
依赖管理是 npm 的核心功能,原理就是执行 npm install 从 package.json 中的 dependencies, devDependencies 将依赖包安装到当前目录的 ./node_modules 文件夹中。
看下不同版本npm的表现
一、npm版本2.15.9

先发布4个npm包
1 | npm-study2@1.0.0 依赖于 npm-study1@1.0.0 |
新建项目,package.json文件如下:
1 | { |
安装依赖
1 | npm install |
node_modules结构:
1 | ├── node_modules |
npm 2.x安装依赖方式比较简单直接,以递归的方式按照包依赖的树形结构下载填充本地目录结构,也就是说每个包都会将该包的依赖安装到当前包所在的node_modules目录中。
二、npm版本3.10.10

删除node_modules,并重新安装依赖
1 | npm install |
node_modules结构:
1 | ├── node_modules |
npm 3.x则采用了扁平化的结构来安装组织node_modules。也就是在执行npm install的时候,按照package.json 里依赖的顺序依次解析,遇到新的包就把它安装在第一级目录,后续安装如果遇到一级目录已经存在的包,会先按照约定版本判断版本,如果符合版本约定则忽略,否则会按照npm 2.x的方式依次挂在依赖包目录下。
package-lock.json文件
npm更新到v5.x.x以后, 会出现一种新的自动生成文件 package-lock.json。
npm为了让开发者在安全的前提下使用最新的依赖包,在package.json中通常做了锁定大版本的操作,这样在每次npm install的时候都会拉取依赖包大版本下的最新的版本。这种机制最大的一个缺点就是当有依赖包有小版本更新时,可能会出现协同开发者的依赖包版本不一致的问题。
package-lock.json文件精确描述了node_modules 目录下所有的包的树状依赖结构,每个包的版本号都是完全精确的。它的的详细描述主要由version、resolved、integrity、dev、requires、dependencies这几个字段构成:
version:包唯一的版本号resolved:安装源integrity:表明包完整性的hash值(验证包是否已失效)dev:如果为true,则此依赖关系仅是顶级模块的开发依赖关系或者是一个的传递依赖关系requires:依赖包所需要的所有依赖项,对应依赖包package.json里dependencies中的依赖项dependencies:依赖包node_modules中依赖的包,与顶层的dependencies一样的结构
切换到npm版本6.4.1,在大版本相同的前提下,以^版本为例,npm-study3依赖包版本有1.3.0,1.4.0,1.6.0还有1.9.0,node_modules下没有该依赖包的情况,那么测试一下package-lock.json的表现:
1)如果一个模块在package.json中的小版本要小于package-lock.json中的小版本,则被package-lock.json中的版本锁定

安装的npm-study3依赖包的实际版本为1.4.0
2)如果一个模块在package.json中的小版本要大于package-lock.json中的小版本

则在执行npm install时,会将该模块更新到大版本下的最新的版本,并将版本号更新至package-lock.json。

安装的npm-study3依赖包的实际版本为1.9.0
更新某个模块大版本下的最新版本(升级小版本号),可以执行以下命令
1 | npm install packageName |
package.json和package-lock.json中的版本号都将会随之更新。
禁用package-lock.json
1 | npm config set package-lock false |
.npmrc文件
通过修改 .npmrc文件可以直接修改配置。系统中存在多个npmrc文件,这些npmrc文件被访问的优先级从高到低的顺序为:
1.项目级的.npmrc文件
2.用户级的.npmrc文件(npm config get userconfig可以看到存放的路径)
3.全局级的.npmrc文件(npm config get globalconfig可以看到存放的路径)
4.npm内置的.npmrc文件