npm介绍
npm是前端项目和 Node.js 项目的包管理工具,从项目开发到更新维护都发挥着重要作用。
- 下载依赖:下载、卸载、更新项目所需的第三方依赖包,并管理依赖版本(如锁定版本、处理冲突)。
- 执行脚本:执行项目中预定义的脚本命令(如
package.json
中scripts
配置),方便项目启动、打包构建等操作。 - 发布包:将自己开发的第三方依赖包发布到 npm仓库,供其他开发者使用和维护。
npm命令
安装项目所有依赖包
# 方式一(完整写法)
npm install
# 方式二(简写)
npm i
当执行 npm install
时:
- 存在
package-lock.json
:- 严格按照其中锁定的精确版本安装依赖(如
vue@2.6.12
) - 无视
package.json
中的版本范围符号(如^
、~
) - 即使远程仓库有更新版本,只要
package-lock.json
未修改,就不会安装新版本
- 严格按照其中锁定的精确版本安装依赖(如
- 不存在
package-lock.json
:- 根据
package.json
中的版本范围安装最新可用版本(如vue: "^2.6.12"
会安装vue@2.7.16
) - 自动生成新的
package-lock.json
,锁定当前安装的版本 - 不会修改
package.json
中的版本声明(仍保留vue: "^2.6.12"
)
- 根据
安装依赖包
当执行 npm install <package>
时,无论是否存在 package-lock.json
,npm都会:
- 根据
package.json
中的版本范围安装最新可用版本。 - 更新
package.json
和package-lock.json
中的版本记录。
例如:若 package.json
中写着 vue: "^2.6.12"
,执行 npm install vue
会安装 vue@2.7.16
(符合 vue: "^2.6.12"
的最新版本),并更新 package.json
和 package-lock.json
中的版本声明。
# 方式一(完整写法)
npm install vue
# 方式二(简写)
npm i vue
安装开发环境的依赖包
开发者日常编写、调试、测试代码的本地环境
# 方式一(默认)
npm install vue
# 方式二(完整写法)
npm install vue --save
# 方式三(简写)
npm install vue -S
自动在 package.json
的 dependencies
字段添加依赖记录,用于生产环境。
{
"dependencies": {
"vue": "^2.7.16"
}
}
安装生产环境的依赖包
应用最终部署并面向用户正式运行的环境
# 方式一(完整写法)
npm install webpack --save-dev
# 方式二(简写)
npm install webpack -D
自动在 package.json
的 devDependencies
字段添加依赖记录,仅用于开发环境。
{
"devDependencies": {
"webpack": "^5.88.2"
}
}
补充说明
dependencies
与 devDependencies
的划分只是一种语义约定,并不强制决定哪些包最终会被打包到产物中。
以 element-plus
为例:它会在 devDependencies
中列出 vue
、vue-router
等库,而这些库实际上是 element-plus
运行时所必需的。
决定哪些包最终会被打包到产物中的核心因素:
- 是否在项目代码中被直接引用(如通过
import
或require
引入) - 是否被构建工具通过
external
配置排除(若被排除,则不会打包进产物)
卸载依赖包
# 方式一
npm uninstall vue
# 方式二
npm r vue
# 方式三
npm remove vue
- 移除
node_modules
中依赖包 - 在
package.json
的dependencies
字段 或devDependencies
字段移除依赖记录。
查看配置
npm config list
查看包的基本信息
npm info md5
查看当前项目的所有包
npm list
检查项目包是否过期
npm outdated
npm不足
占用空间
多个项目的node_modules
中的依赖包是独立存储的,导致同一版本、同一名称的依赖包会在磁盘的不同位置重复出现,极大地浪费了磁盘存储空间。
幽灵依赖
{
"type": "module",
"dependencies": {
"vue": "^3.5.18"
}
}
import { nanoid } from 'nanoid'
console.log(nanoid());
node ./index
nanoid
本身并非项目在 package.json
中直接声明的依赖,而是 vue
内部依赖的包。但由于 npm 会将所有依赖(包括子依赖)尽可能 “提升” 到 node_modules
顶层目录(扁平化处理),使得项目代码中可以直接引入 nanoid
并使用,即便它未被显式声明。
这种情况的隐患在于:
- 若
vue
后续升级时移除了对nanoid
的依赖,项目中直接使用nanoid
的代码会突然报错(依赖断裂)。 - 项目依赖关系不透明,开发者难以从
package.json
中清晰判断哪些包是 “真正被依赖” 的。
npm开发脚手架
创建全局模块软链接
npm link
是 npm提供的一个用于本地模块开发与调试的强大工具,其核心作用是在本地建立模块的软链接,允许你在不发布到 npm仓库的情况下,将本地开发的模块实时应用到其他项目中。
1.创建 a-p-dev
项目并配置 package.json
。
{
"name": "a-p-dev",
"bin": {
"a-p-dev": "bin/index.js"
},
"main": "bin/index.js"
}
- 在项目目录中执行
npm link
。
npm link
-
此时会在全局
node_modules
目录下创建一个指向当前项目目录的软链接。 -
若项目的
package.json
中存在bin
字段,npm会自动在 全局nodejs
目录创建可执行文件:- Windows:
a-p-dev.cmd
、a-p-dev.ps1
(PowerShell 脚本)。 - Linux/macOS:
a-p-dev
(符号链接)。
- Windows:
- 在任意目录的
cmd
行中执行a-p-dev
,即可触发本地项目中bin/index.js
的执行。
补充说明
无论是全局 node_modules
目录下创建的模块目录,还是全局 nodejs
目录下生成的可执行文件(如 a-p-dev
、a-p-dev.cmd
等),其本质都是软链接(符号链接)。
这意味着:
- 这些文件 / 目录并非原项目代码的复制,而是指向本地开发项目真实路径的 快捷方式。
- 当原项目代码(如
bin/index.js
)发生改变时,无需重新执行npm link
,全局引用会实时同步最新代码。
解除全局模块软链接
npm unlink a-p-dev -g
- 删除全局
node_modules
目录下的软链接目录。 - 删除全局
nodejs
目录下的可执行文件。
npm 执行命令
执行当前项目可执行文件
当使用 npm install
安装带有命令行工具的依赖包(如 less
、eslint
)时,这些工具会被安装到项目的 node_modules/.bin
目录中。
以下是三种常用的执行方式:
进入 .bin 目录执行(了解即可)
# 进入项目本地的 .bin 目录
cd ./node_modules/.bin
# 执行命令(例如查看 lessc 版本)
lessc -v
这种方式需要手动切换到 .bin 目录,适合临时验证文件是否存在,日常开发中较少直接使用。
npx
指令
# 无需进入 .bin 目录,直接执行本地命令
npx lessc -v
- 核心特点:
- 自动路径查找:
npx
会优先检索项目node_modules/.bin
目录,无需手动指定路径。 - 临时安装能力:若本地未安装目标命令(如首次使用
create-react-app
),npx
会临时下载并执行,执行结束后,自动清理临时文件,避免全局安装污染环境。 - 版本隔离:确保使用的是当前项目依赖的版本,而非全局版本,减少版本冲突。
- 自动路径查找:
添加scripts
脚本
{
"scripts": {
"less-version": "lessc -v"
}
}
# 执行命令
npm run less-version
特点:
- 简化调用:将长命令或高频操作封装为简短脚本(如
npm run build
),便于记忆和复用。 - 自动路径解析:
npm run
会自动从node_modules/.bin
中查找可执行文件,无需手动拼接路径。 - 支持命令组合:可串联多个命令形成工作流(如
build: "lessc src/style.less dist/style.css && uglifyjs src/index.js -o dist/index.min.js"
)。
NPM发布第三方包
-
创建基础项目
-
注册
npm
账号浏览器打开
https://www.npmjs.com/signup
填好邮箱/用户名/密码。 -
切到官方镜像
# 方式一(推荐,需提前安装 nrm) nrm use npm # 方式二(无 nrm 时直接配置) npm config set registry https://registry.npmjs.org
-
登录
npm login # 依次输入用户名、密码、邮箱、一次性验证码
登录成功后
npm whoami
能看到用户名。 -
发布
npm publish # 根目录执行
-
测试
npm i yeizi
import yeizi from 'yeizi' yeizi() // 就算失败,我也想知道,自己倒在距离终点多远的地方。
避坑指南
-
*镜像源必须切换:发布包前务必将 npm 镜像切回官方源,否则会发布到非官方仓库(如淘宝源)导致失败。
-
版本号手动维护:更新包功能后,需手动修改
package.json
中的version
字段,否则无法重复发布同版本包。 -
包名冲突检查:发布前可在 npm 官网搜索包名,确保包名未被占用,避免发布报错。
疑难问题
npm create vite
实际做了什么?
- 尝试执行
npx @npmcli/create-vite
(官方脚手架前缀)。 - 由于
@npmcli/create-vite
不存在,回退到npx create-vite
。
# 创建项目并选择模板(交互式)
npm create vite my-app
# 直接指定模板(非交互式)
npm create vite my-app -- --template react
注意:--
的核心作用是 “划清界限”:让前半部分的命令只处理自己的选项,后半部分的参数原封不动地传递给被调用的程序 / 脚本,避免歧义或错误解析。在需要向嵌套命令传递参数时,几乎都需要用到 --
。