npm 入门:包管理器、依赖与 npx
一个项目不可能从零写起。今天聊 npm。
为什么需要 npm
代码写到一定阶段,会撞上一个现实:几乎没有哪个项目是从零写完的。
要发 HTTP 请求、要处理时间格式、要压缩图片------这些事早有人做过,而且做得比你好。合理的选择不是重写一遍,而是拿来用。
但"拿来"本身也有成本:去哪里找?用哪个版本?这个包又依赖了哪些别的包?换一台机器,怎么保证装出来是同一套?装到一半发现漏了一个包,怎么补?
npm(Node Package Manager,Node.js 包管理器) 就是解决这一串问题的工具,它是 Node.js 的官方包管理工具,负责三件事:
| 能力 | 说明 |
|---|---|
| 安装包 | 从远程仓库下载第三方代码库(如 express、lodash)到项目中 |
| 管理依赖 | 通过 package.json 记录项目需要的包及版本,确保环境一致 |
| 发布包 | 开发者可以把自己的代码打包发布到 npm 仓库,供他人使用 |
换个更快的理解方式:npm 就是 JavaScript 世界的应用商店。
需要一个"计算器"功能,不必自己写,去商店搜一个、一键安装;商店会记下你装过哪些 App(package.json 干的就是这件事);你写了一个好用的 App,也能传上去给别人下载。
这个思路并不新鲜------Java 世界有 Maven,Python 世界有 PyPI,说的都是同一件事。
核心机制
一、npm 站在 Node 的肩膀上
npm 的名字里带 Node 不是巧合:先有 Node,npm 才有用武之地。
前端页面靠三样东西撑着:
| 角色 | 语言 | 职责 |
|---|---|---|
| 骨骼 | HTML | 提供整体框架与内容承载 |
| 装修 | CSS | 控制颜色、大小、位置 |
| 逻辑 | JavaScript | 处理交互、从远端拉取数据 |
JavaScript 负责第三件事,但它有个先天限制:只能活在浏览器里。 它不能读写磁盘、不能连数据库、不能监听端口。这不是能力不足,而是刻意为之------浏览器里的脚本若能随意读你的硬盘,你存的其他东西也会被一并读走。
打个比方:JavaScript 像餐厅的前厅服务员,帮客人点菜、把菜名写进菜单、检查手机号格式,这些都能做;但服务员进不了厨房,也去不了仓库和收银台。
解除这个限制的,是谷歌 Chrome 里的 V8 引擎------一个用 C++ 写的 JavaScript 解析器,性能极强,而且被整个开源了。程序员 Ryan Dahl 由此想到:JavaScript 凭什么只能待在浏览器里?Python、Ruby、PHP 能做的事,它也该能做。
于是他带团队把 V8 从浏览器里拆出来,做成一套独立的运行时,命名为 Node.js(现在也常简称为 Node)。可以理解为给 JavaScript 配了一张"万能厨房通行证":操作文件、连接数据库、监听服务器端口,这些后端能力它都有了。
顺带一提,Node 官网(https://nodejs.org/en)上的版本不是随便选的。要留意每个版本的生命周期:一旦进入 EOL(End of Life,停止维护),就不再接收修复,安全漏洞可能被引入。选型时挑仍在维护的稳定版本,通常选最新的 LTS 或退一档的版本更稳妥。
二、npm 管的东西,落在哪里
npm 官网是 https://www.npmjs.com/,上面托管着超过 200 万个开源包(截至 2025 年),每周下载量以十亿计。
它的功能可以归成四条:安装卸载更新依赖包、管理项目的包信息、运行定义的脚本、发布自己的包。其中最需要分清的是安装位置:
| 命令 | 作用范围 |
|---|---|
npm install <pkg> |
局部安装,装进当前项目 |
npm install -g <pkg> |
全局安装,装到系统级目录,任何地方都能调用 |
判断标准很简单:这个包是项目要用 ,还是你要用。项目依赖走局部,命令行工具走全局。
至于"依赖"这个词,展开说一句:你写了一个 C 包,内部用了别人的 A 包和 B 包,那么 C 就依赖 A 和 B。当你把 C 发布出去,别人安装 C 的时候,A 和 B 会被一并装好------版本对应关系由 npm 处理,不需要使用者手动梳理。
三、npx:npm 负责"拥有",npx 负责"使用"
npx(Node Package Executor,包执行器) 从 npm 5.2.0 起被内置进 npm,装了较新的 Node 就自带。它允许直接运行 npm 仓库里的包,无需先用 npm install 把它永久装上。
一句话概括两者分工:npm 负责"拥有"包,npx 负责"使用"包。
| 维度 | npm | npx |
|---|---|---|
| 定位 | 包管理器(管理依赖) | 包执行器(运行命令) |
| 主要操作 | 安装、卸载、更新、发布 | 执行命令、临时运行 |
| 是否需预先安装包 | 是,运行前必须先 npm install |
否,可直接运行,临时下载 |
| 是否全局安装 | 装完后包长期存在于 node_modules 或全局目录 |
未全局安装 |
| 典型场景 | 长期依赖管理、项目初始化 | 临时命令、脚手架一次性创建 |
它查找命令的顺序是:当前项目的 node_modules/.bin/ → 全局安装 → 临时下载最新版。这个顺序解释了它为什么好用------先看你项目里有没有,再看全局有没有,都没有才去临时拉一个。
代码演示
一、装 Node,有两处必须改
从官网 https://nodejs.org/en 进入下载页,选对应系统的安装包,安装过程一路下一步即可。装完打开命令行验证:
bash
node -v
能正常打印版本号,说明安装成功。npm 和 npx 是随 Node 一起来的,一并确认:
bash
npm -v
npx -v
两者版本号一致(例如同为 11.11.0),因为它们本就是同一个 npm 的两副面孔。
第一处要改:镜像源。 npm 默认从国外的 registry.npmjs.org 取包,国内访问经常很慢。换成淘宝镜像源:
bash
npm config get registry
npm config set registry https://registry.npmmirror.com
npm config get registry
第一步和第三步是同一个命令------先看改之前是什么,改完再确认一次,这是改配置的通用习惯。
这一步本质上只是把域名换掉 :registry.npmjs.org 与 registry.npmmirror.com 是两个不同的域名,各自解析到不同的服务器,请求自然会落到离你更近的那台上。
📖 参考:《计算机网络知识库》第五节
第二处要改:全局包的安装目录。 默认位置在 C 盘,全局包一多容易把系统盘撑满。先在别的盘建两个目录(例如 D:\lib\node_global 与 D:\lib\node_cache),再指过去:
bash
npm config set prefix "D:\lib\node_global"
npm config set cache "D:\lib\node_cache"
npm config list
路径需要按自己的实际目录改。还有一步别漏:把 node_global 加进系统的 PATH 环境变量,否则全局装的命令行工具会提示"找不到命令"。
二、用 npm 装一个包
拿经典的 cowsay 练手最合适------功能极简单:让一头小牛在终端里说出你指定的话。
bash
npm install -g cowsay
装完直接调用:
bash
cowsay "Hello Bite"
text
____________
< Hello Bite >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
这头牛是从哪来的?cowsay 本身是一个 npm 包,npm install -g 把它下载并安装到了你刚才配置的 node_global 目录下,再把可执行文件挂进 PATH,于是敲 cowsay 就能唤醒它。整个链条到此闭合。
三、用 npx 跑一个包,不装也行
同一个 cowsay,这次不安装,直接跑:
bash
npx cowsay "Hello, 比特!"
text
______________
< Hello, 比特! >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
包没装进任何地方,用的时候临时取来,用完即走。不常驻、不占目录,这就是 npx 存在的理由------一次性的工具,没必要为它做一次永久安装。
当然,如果这个包你每天都要用,还是老实 npm install -g,别每次让 npx 重新下载。
常见误区
把什么都装成全局的。 npm install -g 看着方便,但全局包不写进 package.json,别人拿到你的项目跑不起来。判断标准只有一条:项目依赖走局部,命令行工具才走全局。
不换镜像源就抱怨 npm 慢。 默认源在境外,慢是正常现象,改一行配置就能解决,不必反复重试。
在 Node 版本上随便选。 挑到已进入 EOL 的版本,等于放弃了后续的安全修复。选型前先查版本维护时间表。
以为 npx 是 npm 的替代品。 两者不是竞争关系:npm 管安装与依赖,npx 管执行,装 Node 时两个一起到齐。
配好了全局目录,却漏了 PATH。 自定义 prefix 之后不把该目录加进环境变量,全局工具会一直提示"找不到命令"------包装对了,是系统不知道去哪找。
本节要点
- npm(Node Package Manager)是 Node.js 的官方包管理器,管三件事:安装包、管理依赖、发布包。
- 它的能力建立在 Node 之上;Node 本身是把 V8 引擎从浏览器里拆出来做的独立 JavaScript 运行时。
- 局部安装给项目,全局安装给命令行工具------判断标准是"项目要用"还是"你要用"。
- npx(npm 5.2.0 起内置)负责"使用"包:不安装也能跑,适合一次性命令与脚手架。
- 装完 Node 记得做两件事:换国内镜像源、改全局包目录并配好 PATH。
相关:MCP 入门:从 m×n 到 m+n------那篇里一带而过的 npx,本篇展开了