npm是服务+客户端+注册中心的组合体,不打包编译,只负责依赖管理;装全局或本地取决于-g参数及是否在含package.json的项目根目录。
npm 是 JavaScript 生态中事实上的包管理器,不是“工具”而是“服务+命令行客户端+注册中心”的组合体。它本身不打包、不编译,只负责下载、安装、解析依赖关系和执行脚本。
关键看有没有 -g 参数,以及当前是否在项目根目录(含 package.json):
npm install lodash → 装到当前项目的 node_modules 下,写入 dependencies
npm install -D eslint → 装到 node_modules,但写入 devDependencies
npm install -g create-react-app → 装到系统级路径(如 /usr/local/lib/node_modules),所有终端都能直接运行 create-react-app
⚠️ 注意:npm install(不带参数)会读取当前 package.json,按 dependencies 和 devDependencies 自动重装所有包 —— 这是团队协作时的标准操作,不是“重复安装”。
区分逻辑很简单:运行时是否必须存在。
dependencies:代码里 require('react') 或 import axios from 'axios' → 必须打进生产包,用户浏览器或 Node 服务启动时需要devDependencies:只在开发阶段用,比如 webpack、jest、prettier → 构建完就扔,上线不带它们装错会导致两种典型问题:Cannot find module 'xxx'(漏进 dependencies),或生产环境体积暴涨(误塞构建工具进 dependencies)。
根本原因是 npm 默认采用嵌套式依赖结构(v6 及以前),不同包的相同子依赖可能被重复安装多次。v7+ 默认启用 dedupe,但仍可能因版本冲突无法扁平化。
真正可控的做法是:
npm ci 替代 npm install 上 CI/CD 或部署机 —— 它严格按 package-lock.json 安装,跳过依赖解析,更快更确定node_modules 前先确认 package-lock.json 存在且未被忽略(.gitignore 不该加它)npm update 随意升版,改用 npm outdated 查看可更新项,再 npm install xxx@latest 显式指定npm outdated # 输出类似: # Package Current Wanted Latest Location # lodash 4.17.20 4.17.21 4.17.21 my-project
最常见两类权限和路径错误:
EACCES: permission denied → 多半是用了 sudo npm install -g 导致后续全局写入权限混乱。正确解法是改 npm 全局路径:mkdir ~/.npm-global npm config set prefix '~/.npm-global' # 然后把 ~/.npm-global/bin 加进 $PATH
ENOENT:
no such file or directory → 通常是 package-lock.json 记录了某个包的 tarball URL,但网络抽风或 registry 切换(比如从 npmjs.org 换成 taobao)导致下载失败。临时切回官方源:npm set registry https://registry.npmjs.org/
第三方 registry(如 https://registry.npmmirror.com)虽快,但镜像同步有延迟,某些刚发布的包可能查不到 —— 这点容易被忽略,尤其当你盯着一个新包的文档却死活 install 不上时。