Node、NVM与npm前置知识
Node、NVM 与 npm 前置知识
学 Vue 的第一步不是写代码, 是装环境。Vue 项目不能双击 index.html 直接跑, 开发服务器、装依赖、打包全都建立在 Node 这套工具链上。
这篇把 Node / nvm / npm 到底是什么、互相什么关系讲清楚, 再记下 Windows 上装环境的几个坑 (都是我真踩过的)。
npm 和模块化的概念在工具链篇首讲过, 这篇偏”动手装环境”视角, 两边互相补。
1. 一张关系图, 一套 Java 对照
flowchart LR
NVM[nvm 版本管理] --> NODE[Node.js 运行时]
NODE --> NPM[npm 包管理器]
NODE --> NPX[npx 临时执行器]
NPM --> PKG[package.json]
NPM --> LOCK[lockfile]
NPM --> MOD[node_modules]
NPM --> VITE[Vite]
VITE --> APP[Vue 应用]
对写 Java 的人, 整套东西都有现成的对应物, 一次对齐:
- Node.js 之于 JS, 就是 JVM/JRE 之于 Java: 让代码离开浏览器也能跑的运行时。Vite、脚手架这些工具本身都是 JS 写的, 靠 Node 跑起来。
- npm 就是前端的 Maven: 管依赖下载、管项目命令。
package.json就是pom.xml: 声明项目叫什么、依赖哪些包、有哪些命令。node_modules对应依赖仓库, 但有个关键差异: Maven 的仓库是全局一份 (~/.m2), npm 默认把依赖装进每个项目自己的node_modules文件夹, 所以每个项目都有一坨几百 MB 的目录, 删了也能重装回来。- nvm 用来装多个 Node 版本并随时切换。我机器上 JDK 17 和 Oracle 24 在 PATH 里打过架, Node 世界里同样的戏码更常见, nvm 就是给这事的正规解法。
2. Node.js 到底是什么
一句话: 基于 Chrome V8 引擎、能在操作系统上直接运行 JS 的运行时, 补上了浏览器没有的能力 (读写文件、起服务器、开进程)。它和 Vue 没有绑定关系, 只是 Vue 的工具链恰好都是 Node 程序。
代码块收起展开
node -v # 看版本
node -e "console.log(1 + 2)" # 直接执行一段 JS, 类似 java 直接跑段代码
node -p "process.execPath" # 打印当前用的是哪个 node.exe, 排查多版本时救命最后那条命令值得记住: node -v 只告诉你版本号, 查”到底在用哪套安装”得看路径。Windows 上再配一句 where.exe node, 列出 PATH 里所有能搜到的 node, 排前面的生效。
3. nvm: 给 Node 版本上管理
不同项目可能要求不同的 Node 版本 (看 package.json 里的 engines 字段), 反复卸载重装太蠢, nvm 让多个版本共存、一条命令切换。
Windows 上装的是 nvm-windows, 和 Linux/macOS 的 nvm 是两个不同实现, 网上 Unix 教程里的 source nvm.sh 那套别往 PowerShell 里粘。
代码块收起展开
nvm list # 已装的版本
nvm install 22.14.0 # 装一个指定版本
nvm use 22.14.0 # 切换
nvm current # 当前生效的版本选版本的原则: 优先 LTS (长期支持版, 生态兼容最稳), 项目有 engines 要求就以项目为准。
踩过的坑记三条:
nvm use切换后, 已经开着的终端还缓存着旧 PATH,node -v看着没变。关掉终端重开就好。- IDE 内置终端和外部 PowerShell 的 PATH 可能不一样, 一边能跑一边报”不是命令”。
- 最阴的一种:
node来自 nvm 的链接目录,npm却来自另一套旧安装, 各自都”存在”但版本不配套。所以自检时 node 和 npm 的路径要一起看, 确认来自同一套安装。
4. npm: 前端的 Maven
npm 干三件事: 从仓库下载依赖包、执行 package.json 里定义的命令、维护依赖版本锁定。
代码块收起展开
npm -v # npm 自己的版本
npm config get registry # 当前从哪个仓库下包 (对应 Maven 的中央仓库/镜像地址)
npm view vue version # 查 vue 这个包在仓库里的最新版本registry 就是包的下载源, 国内慢可以换镜像, 这和 Maven 配阿里云镜像完全一个逻辑。
npm create vue@latest 逐词拆解
学 Vue 第一条要跑的命令, 每个词都有含义:
npm create xxx是个约定: 实际去下载并执行一个叫create-xxx的脚手架包。所以这条命令真正跑的是create-vue, Vue 官方的项目生成器。@latest指定版本标签, 意思是”用仓库里最新发布的那个版本”, 保证脚手架不是本地缓存的老版本。- 跑起来后它会问一串问题 (要不要 TypeScript、Router、Pinia 等), 按需勾选, 生成一个完整的项目骨架。
顺便认识 npx: 临时执行一个包的命令行工具, 优先用项目 node_modules 里装的, 没有就从仓库现下现跑。适合一次性命令; 团队日常命令还是应该写进 package.json, 别依赖每个人临时下载。
5. 项目三件套: package.json、lockfile、node_modules
代码块收起展开
{
"name": "vue-project",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"vue": "^3.5.0"
},
"devDependencies": {
"vite": "^7.0.0"
}
}scripts: 自定义命令。npm run dev就是执行这里dev对应的vite。dependencies: 应用运行需要的包 (Vue 本体、Router)。devDependencies: 只有开发和构建时用的包 (Vite、TypeScript),npm install -D xxx装进来。private: true: 防止手滑把项目发布到公共仓库。
版本号前的符号是允许的更新范围: ^3.5.0 表示可以升 minor/patch 但不跨大版本 (3.x 内随便), ~3.5.0 只允许 patch (3.5.x)。Maven 里我们习惯写死版本, npm 生态习惯给范围, 那”实际装的到底是哪个版本”谁说了算? 答案是 lockfile。
package-lock.json 记录本次解析出的完整依赖树和每个包的精确版本, 保证换台机器 npm install 装出一模一样的结果。它必须提交 Git; node_modules 则永远不提交 (几百 MB 且可由 lockfile 完整重建)。
两条命令的分工: 日常开发用 npm install (会按需更新 lockfile); CI/部署用 npm ci (严格按 lockfile 装, 先清空 node_modules, lockfile 和 package.json 对不上直接报错)。
6. npm run dev 为什么能找到 vite
直接在终端敲 vite 大概率报”不是命令”, 但 npm run dev 就能跑。原因: npm 执行 scripts 时会临时把项目的 node_modules/.bin 塞进 PATH, 里面有本地安装的 vite 启动器。这个设计保证了大家用的都是项目里锁定的那个版本, 而没有全局装一堆工具。
给脚本传参数要加 -- 分隔:
代码块收起展开
npm run dev -- --port 5174 # 第一个 -- 之后的参数原样传给 vite7. 环境自检清单
新机器或者环境行为诡异时, 按这个顺序过一遍:
代码块收起展开
node -v
npm -v
npx --version
where.exe node # 多个结果时, 排最前的生效
where.exe npm # 必须和 node 同一套安装
npm config get registry确认三件事: node/npm/npx 来自同一套安装; Node 版本满足项目 engines; registry 能访问。环境问题的排查顺序永远是先工具链、再项目配置、最后才怀疑代码。别一上来就删 node_modules 重装, 先读第一条真实报错。
8. 从零到跑起来的完整顺序
- 确认 node/npm 版本与路径
npm create vue@latest(按需勾选)- cd 项目目录,
npm install npm run dev, 浏览器打开终端给的地址
跑通之后, 项目里每个文件是干嘛的去看前端文件架构, Vue 本体的学习从快速上手篇开始。
9. 动手验收
- 用 nvm 装两个 Node 版本并切换, 每次切完用
node -p "process.execPath"确认路径真的变了。 - 创建一个 Vue 项目, 口述 package.json、lockfile、node_modules 三者各自的角色。
- 删掉 node_modules, 用
npm ci恢复, 验证项目照常能跑。 - 用
npm run dev -- --port 5174换端口启动一次, 说清楚两个--各是给谁的。