转载:https://blog.csdn.net/why_1639946449/article/details/137555677
前言🔖
问题1.在 vue-cli2或者 vue-cli3 中,当我们创建好一个项目,我们要通过 npm run dev(vue-cli2的命令,vue-cli3之后用npm run serve,原理都一样,只不过是换了一下名字而已)运行一个项目。或者通过 npm run build 打包一个项目。那么问题来了,当我们在命令框中输入这两个命令的时候:
- 这背后到底是做了什么
- 是谁帮我们做的这些事
问题2.在前端开发中,npm run serve 是一个常见的命令,尤其是在使用 Vue CLI 构建项目时。但是为什么直接运行 vue-cli-service serve 会报错,但使用 npm run serve 却可以成功启动项目呢?
前置知识:npm scripts 的基本原理🔖
先回顾一下 npm 命令的基本原理。在 package.json 文件中的 “scripts” 字段允许我们定义一组自定义的命令。例如:
"scripts": {
"start": "node index.js",
"serve": "vue-cli-service serve",
// 其他命令...
}
这里 "serve" 就是我们需要执行的命令,其对应的值是执行 vue-cli-service serve。运行 npm run serve 实际上是在执行 vue-cli-service serve 命令。
🔹为什么直接运行 vue-cli-service serve 会报错?
直接运行 vue-cli-service serve 会导致错误的主要原因在于 vue-cli-service 不是一个全局可执行命令,而是作为项目依赖安装在项目的 node_modules 中。
运行 vue-cli-service serve 时,操作系统并不知道去哪里找这个命令。而通过 npm run serve,我们在 package.json 的 “scripts” 中定义了 serve 对应的命令是 vue-cli-service serve,这时 npm 根据查找规则就能够正确找到并执行这个命令。
🔹npm run serve 查找规则
npm run serve 的执行过程涉及以下步骤:
- 查找命令:npm 首先在当前项目目录的 node_modules/.bin 目录下查找是否存在 vue-cli-service 可执行文件。
- 查找全局安装:如果在项目的 node_modules/.bin 中没有找到 vue-cli-service,npm 会继续在全局 node_modules/.bin 目录下查找
- 执行命令:找到
vue-cli-service后,npm将执行该命令
这个查找过程确保了我们可以在项目内部或全局的依赖中找到并执行指定的命令,相当于执行了 ./node_modules/.bin/vue-cli-service serve
🔹npm scripts 的命令注入机制
在执行 npm run serve 时,npm 实际上会将项目的 node_modules/.bin 目录添加到系统的 PATH 中。这个目录包含了大部分通过 npm install 安装的可执行文件,其中也包括了 vue-cli-service。
这样一来,系统就能够在全局范围内找到 vue-cli-service 命令,不用在命令行中指定完整的路径。
🔹全局安装
当某个包被全局安装时,其可执行文件也会被放置在全局 node_modules/.bin 目录中。如果全局的 node_modules/.bin 目录也被加入系统的 PATH 中,那么在全局范围内就可以运行该可执行文件。
这种机制使得一些工具和命令行程序能够在任何地方都能被直接调用,而无需指定完整路径。
🔹vue-cli-service 来自哪里
vue-cli-service 命令是 Vue CLI 提供的可执行文件,在项目初始化时会自动创建一个 .bin 目录,其中包含了一些项目本地的可执行文件。
当我们通过 Vue CLI 创建一个新的 Vue.js 项目时,它会在项目的 node_modules/.bin 目录下创建一个名为 vue-cli-service(或者是 vue-cli-service.cmd,这取决于你使用的是 Windows 还是其他系统)的可执行文件。
这个可执行文件实际上是指向项目安装的 @vue/cli-service 包中的 bin/vue-cli-service.js 文件的一个软链接,这个文件是 Vue CLI 提供的命令行工具的入口文件。
当我们在 package.json 文件的 “scripts” 字段中使用 vue-cli-service 命令时,实际上是在调用这个项目本地的可执行文件,而不是全局安装的 Vue CLI。
好处在于每个 Vue.js 项目都可以有自己的 vue-cli-service 可执行文件,这样可以确保在不同的项目中使用不同版本的 Vue CLI 而不会相互影响。
🔹npm scripts 进阶用法
除了简单的命令,npm scripts 还支持并行执行多个命令,以及通过插件实现更高级的功能。以下是一个使用 npm-run-all 插件实现并行执行命令的例子:
"scripts": {
"start": "npm-run-all --parallel task1 task2",
"task1": "command1",
"task2": "command2"
在这个例子中,npm run start 将同时执行 task1 和 task2。
准备工作🔖
首先我们先来创建一个vue项目,这里需要说明一下,我们也可以不用非得创建一个vue的项目,创建一个文件夹,然后在里面创建几个js文件,也可以。不过我们现在都对vue比较熟悉,我们就以vue项目为例。
好,先来创建一个vue项目,在命令行中输入命令:vue create test-vue
我的vue-cli版本是4.4.6,所以要通过这行命令创建。其它版本的可以查一下官方文档。这里不过多解释。
当创建好之后出现以下提示,说明项目已经创建好了
用vscode打开项目,看一下文件目录:

这是vue-cli这个脚手架工具帮我们创建是默认目录。
这背后到底是做了什么🔖
我们在命令行中输入命令:
npm run serve
看一下运行成功之后的提示信息:

有没有小伙伴想过这样的问题:为什么是运行npm run serve命令呢,这些命令在哪里呢,我该怎么记住这些命令。
其实这个命令不需要记这个命令,我们只要记住 npm run就好,当我们创建完项目之后可以看到一个 package.json文件。看一下主要的内容:文件内容过多,我们主要看一下 script标签的内容
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
}
聪明的小朋友可能已经明白了,会不会我们 npm run serve 就是执行的的第一行吧。其实是对的,当我们输入 npm run 之后,就是相当于运行 vue-cli-service serve 这行指令。这个名称可以改,我们改成 dev 之后,就是 npm run dev。不知小伙伴是否明白了。
🔹是谁帮我们做的这些事
那么又是谁帮我们把项目运行起来的呢?我们继续看:当输入 npm run serve回车执行的时候,npm会在项目的目录下找到 node_modules文件夹下的 .bin目录,把此目录添到系统的path环境变量下,执行完之后再把环境变量下的目录删除。打开这个文件夹可以看到一个文件:vue-cli-service这其实是一个 link 快捷方式,它指向 @
vue/cli-service/bin/vue-cli-service.js这个文件。
npm run serve 就是在运行这个vue-cli-service.js脚本文件。看一下里面的一些代码:
const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
// ....省略了一些代码
const command = args._[0]
service.run(command, args, rawArgv).catch(err => {
error(err)
process.exit(1)
})
这里其实就是开启了一个node服务。
总结:
- 当我们在命令行中输入 npm run xxxx的时候,其实就是执行 package.json文件里的 scripts里的某个命令
- npm run serve命令之后,就是开启了一个服务来运行我们的项目,这是 WebpackDevServer开启的服务
来自豆包的回答🔖
🔹npm run serve 到底做了什么?
我们一步步拆解这个命令的执行逻辑:
- 1. 第一步:npm 读取配置
当你在终端执行 npm run serve 时,npm 会先去项目根目录的 package.json 文件中,查找 scripts 字段里名为 serve 的脚本配置。
一个标准 Vue 项目的 package.json 里,scripts 通常长这样:
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
}
简单说:npm run serve 本质是 npm 帮你执行了 vue-cli-service serve 这个底层命令。
- 2. 第二步:vue-cli-service 工作
vue-cli-service是 Vue CLI 提供的核心工具(你可以理解为 “Vue 项目的管家”),它会做这些核心操作:- 加载配置:读取
vue.config.js(如果有)、package.json中的 Vue 相关配置,以及默认的 Webpack 配置; - 启动开发服务器:基于 Webpack Dev Server 启动一个本地 HTTP 服务(默认端口 8080);
- 编译代码:通过 Webpack 把你的
.vue文件、ES6+ 代码、CSS 等 “浏览器不认识的代码” 编译成浏览器能解析的 HTML/CSS/JS; - 热更新(HMR):监听文件变化,修改代码后无需手动刷新页面,自动更新内容(这是开发时的核心便利点);
- 输出日志:在终端显示启动成功的提示、访问地址(如
http://localhost:8080)、编译错误 / 警告等。
- 加载配置:读取
- 3. 第三步:浏览器访问
当上述步骤完成后,本地服务器会把编译后的代码 “托管” 在指定端口,你在浏览器输入 http://localhost:8080 就能看到 Vue 项目的页面 —— 这就是 “运行 Vue Web 项目” 的本质。
🔹为什么它能运行 Vue Web 项目?
核心原因有 3 点:
- 依赖前端工程化工具链Vue 项目的
.vue单文件组件、ES6+ 语法、SCSS/LESS 等,浏览器本身无法直接解析,而vue-cli-service内置了 Webpack、babel、vue-loader 等工具:vue-loader:解析.vue文件,把 template/style/script 拆分后分别处理;babel:把 ES6+ 转成 ES5,兼容更多浏览器;css-loader/style-loader:处理 CSS,注入到页面中。
- Webpack Dev Server 提供服务它不是把编译后的文件写到硬盘(区别于
npm run build),而是把文件放在内存中,通过 HTTP 服务暴露给浏览器,同时监听文件变化,实现 “热更新”,让开发体验更流畅。 - Vue 自身的运行时编译后的代码会加载 Vue 核心库(vue.runtime.esm.js),创建 Vue 实例、挂载 DOM、处理响应式数据 —— 这是 Vue 能在浏览器中渲染页面的基础。
🔹补充:关键细节
- 如果你改了
package.json中serve脚本的内容(比如改成vue-cli-service serve --port 8081),npm run serve就会执行新的命令(比如指定端口 8081); vue-cli-service是通过 npm 安装的(在node_modules/.bin目录下),所以只有安装了项目依赖(npm install)后,才能执行这个命令;- 生产环境不会用
serve,而是用npm run build编译成静态文件,再用 Nginx/Apache 等 Web 服务器部署。
🔹总结
npm run serve是 npm 调用package.json中配置的vue-cli-service serve命令;- 底层是 Vue CLI 借助 Webpack 编译 Vue 代码,并通过 Webpack Dev Server 启动本地 HTTP 服务;
- 最终浏览器通过访问本地服务,加载编译后的代码,运行 Vue 项目的 Web 页面。
简单记:npm run serve = 读取脚本配置 → 编译 Vue 代码 → 启动本地服务器 → 浏览器访问。