一、一句话区分
| 命令 | 本质 | 通俗理解 |
|---|---|---|
node index.js | 直接执行 JS 文件 | 像直接双击打开一个.exe程序 |
npm run dev | 执行 package.json 里定义的脚本 | 像按一个"启动按钮",背后可能是一串复杂操作 |
二、node命令:最原始、最直接
2.1 基本用法
node文件名.js示例:
nodeindex.jsnodeserver.jsnode./src/app.js2.2 它做了什么?
Node.js 直接读取这个 JS 文件,逐行解释执行,就这么简单。
特点:
- ✅ 简单直接,没有任何中间环节
- ✅ 启动速度快(没有额外开销)
- ✅ 适合跑独立脚本、工具脚本
局限:
- ❌ 不会自动加载项目依赖(比如
express、lodash) - ❌ 不会自动设置环境变量
- ❌ 不会自动编译 TypeScript、转义 JSX 等
- ❌ 命令长了不好记(比如要传很多参数)
三、npm run命令:包装过的"快捷方式"
3.1 基本用法
npmrun 脚本名示例:
npmrun devnpmrun startnpmrun buildnpmruntest3.2 这些命令从哪来?
来自项目根目录的package.json文件里的scripts字段:
{"name":"my-project","scripts":{"dev":"nodemon server.js","start":"node server.js","build":"webpack --mode production","test":"jest"}}npm run dev实际上执行的是:nodemon server.js
3.3 它做了什么?
npm帮你做了很多事:
- 读取
scripts定义:找到dev对应的命令 - 加载本地依赖:优先使用
node_modules/.bin/里的命令(比如nodemon、webpack) - 设置环境变量:可以自动注入
NODE_ENV等 - 执行最终命令:把解析后的完整命令跑起来
特点:
- ✅ 命令简短好记(
npm run dev比nodemon --watch src --ext js server.js好记多了) - ✅ 团队共享配置(同事 clone 下来直接
npm run dev就能跑) - ✅ 可以做复杂操作(编译、打包、测试、启动一条龙)
- ✅ 自动找本地安装的命令(不用全局安装)
四、核心区别对比
| 对比维度 | node index.js | npm run xxx |
|---|---|---|
| 执行对象 | 直接执行 JS 文件 | 执行package.json里定义的脚本命令 |
| 依赖处理 | 不会自动处理,需手动确保依赖已安装 | 自动从node_modules找命令和包 |
| 命令长度 | 写全路径和参数,可能很长 | 一个短词搞定,背后逻辑藏在配置里 |
| 环境变量 | 手动设置 | 可在scripts里预设,或通过.env加载 |
| 团队共享 | 每个人记自己的命令 | 配置在package.json里,团队统一 |
| 适用场景 | 跑简单脚本、学习测试 | 正式项目开发、团队协作 |
五、实际场景举例
场景 1:写一个"Hello World"
项目结构:
hello/ └── index.jsindex.js:
console.log('Hello World');怎么做?
nodeindex.js不需要npm,因为这就是一个孤立的 JS 文件,没有依赖,没有复杂配置。
场景 2:开发一个 Express 后端项目
项目结构:
my-api/ ├── package.json ├── node_modules/ ├── .env └── server.jspackage.json:
{"scripts":{"dev":"nodemon server.js","start":"node server.js","test":"jest"}}为什么不用node server.js?
| 需求 | node server.js | npm run dev |
|---|---|---|
| 代码改了自动重启 | ❌ 不支持 | ✅nodemon自动监听 |
加载.env环境变量 | ❌ 不会自动加载 | ✅ 可在脚本里配dotenv |
| 团队统一命令 | ❌ 每个人写法可能不同 | ✅ 看package.json就知道 |
用本地安装的nodemon | ❌ 需全局安装或写长路径 | ✅npm自动找node_modules/.bin/nodemon |
场景 3:前端 React 项目
package.json:
{"scripts":{"dev":"vite","build":"vite build","preview":"vite preview"}}为什么不能用node直接跑?
因为 React 代码是 JSX + ES6+,浏览器和 Node.js 都不能直接运行,需要经过vite或webpack编译转换。npm run dev背后启动了一个开发服务器,帮你做了编译、热更新、代理等一堆事。
# 这样不行 ❌nodesrc/App.jsx# 这样才行 ✅npmrun dev六、常见误区
误区 1:npm run比node快?
错。npm run本质上最后也是调用node或其他命令,中间多了npm解析package.json的过程,反而慢一点。它的价值在于方便和统一,不是速度。
误区 2:npm run start和node index.js完全一样?
不一定。虽然很多项目的start脚本就是node index.js,但也可以包装更多逻辑:
{"scripts":{"start":"NODE_ENV=production node dist/server.js"}}这里npm run start不仅启动了服务,还设置了生产环境变量,并且运行的是编译后的dist/server.js,而不是源码。
误区 3:没有package.json就不能用npm?
对。npm run必须依赖package.json。如果你只有一个孤立的.js文件,直接用node就行。
七、怎么选?一张图看懂
┌─────────────────────────────────────────────────┐ │ 你只有一个 .js 文件,没有依赖,没有 package.json? │ │ → 直接用 node 文件名.js │ └─────────────────────────────────────────────────┘ ↓ 有 package.json ┌─────────────────────────────────────────────────┐ │ 你在做项目开发,有依赖、有脚本配置? │ │ → 用 npm run xxx │ │ · 开发调试 → npm run dev │ │ · 启动服务 → npm run start / npm start │ │ · 构建打包 → npm run build │ │ · 运行测试 → npm run test / npm test │ └─────────────────────────────────────────────────┘八、总结
node | npm run | |
|---|---|---|
| 角色 | Node.js 运行时本身 | 包管理器 + 脚本执行器 |
| 作用 | 直接执行 JS 代码 | 执行预定义的脚本命令 |
| 关系 | 底层执行者 | 上层指挥官,最后可能还是调用node |
| 记住 | 像直接踩油门 | 像按"自动驾驶"按钮 |
一句话:node是发动机,npm run是方向盘上的快捷键。写小脚本直接踩油门(node),做项目按快捷键(npm run)。