1. 为什么“装个脚手架”要讲三种方式?——从一次团队协作事故说起
去年在带一个跨部门前端协作项目时,我遇到过这样一幕:三位刚入职的新人,面对同一份《环境搭建指南》文档,分别用了三台开发机,花了整整两天才把@vue/cli跑起来。A同学用 npm 全局安装,结果被公司内网镜像源卡死;B同学照着某篇2021年的教程用 cnpm,结果vue create命令报错说“找不到 vue-cli-service”;C同学直接下载了 Node.js 官方安装包,却因没清空旧版 npm 缓存,导致vue --version显示的是 4.5.13——而项目要求必须是 5.x+。最后三人凑在一起对比终端输出,才发现问题根本不在“会不会”,而在“在哪装、怎么装、装给谁用”。
这件事让我意识到:@vue/cli不是一个“点一下就完事”的安装包,它是一套运行时环境决策系统。它的安装方式,本质上是在回答三个关键问题:
- 这个 CLI 是给当前用户个人用,还是给整个团队统一约束?
- 你希望它和项目强绑定(避免版本漂移),还是保持全局可用(快速启动新项目)?
- 你的网络环境、CI/CD 流水线、甚至未来是否要迁移到 pnpm 或 Bun,是否已被纳入考量?
所以,“三种方式”不是为了炫技,而是对应三种真实生产场景:
✅全局安装→ 适合单人快速原型验证、教学演示、本地命令行高频调用;
✅局部安装 + npx 调用→ 适合团队协作项目、CI/CD 自动化构建、多项目版本隔离;
✅项目级依赖 + package.json 脚本封装→ 适合中大型工程、需要精确控制 CLI 行为(如自定义 preset、插件链)、或需与 Vue 版本做语义化对齐的场景。
这三种方式背后,是 Node.js 模块解析机制、npm 生命周期钩子、以及现代前端工程化对“确定性”的底层诉求。接下来,我会用实操细节、错误日志还原、参数原理拆解,带你真正搞懂每一种方式“为什么这么装”“装完之后到底发生了什么”“哪些坑我踩过你别再踩”。
提示:本文所有命令均基于 Node.js v18.17.0 + npm v9.6.7 实测验证,不兼容 Node.js < 16.14 的旧环境。若你仍在用 Node.js 14,请先升级——这不是建议,是硬性前提。Vue CLI 5.x 已彻底放弃对 Node.js 14 的支持,强行安装会导致
create命令静默失败,且无任何有效报错提示。
2. 全局安装:最直觉,也最容易埋下“版本地雷”
2.1 执行命令与底层发生了什么?
最常被教程推荐的方式是:
npm install -g @vue/cli但这条命令背后,远不止“把文件拷到某个目录”那么简单。我们来拆解它的完整执行链路:
- npm 解析
-g标志:npm 会读取npm config get prefix的值(通常是/usr/local或C:\Users\用户名\AppData\Roaming\npm),并在此路径下创建lib/node_modules/@vue/cli目录; - 符号链接注册:npm 同时在
prefix/bin目录(如/usr/local/bin)下生成可执行文件vue,该文件实际指向lib/node_modules/@vue/cli/bin/vue.js; - PATH 环境变量生效:你的 shell 启动时会将
prefix/bin加入PATH,因此终端能直接识别vue命令; - 运行时加载逻辑:当你输入
vue create my-project,vue.js主程序会动态加载@vue/cli包内的create.js,再由create.js初始化项目模板、调用@vue/cli-service等子模块。
这个过程看似顺畅,但隐患藏在第 2 步和第 4 步之间——全局安装的@vue/cli和你项目里node_modules中的@vue/cli-service并非同一套代码。前者只负责“创建项目”,后者才真正驱动开发服务器、打包构建。它们的版本可以完全不一致。
2.2 一个真实报错:vue-cli-service找不到的根源
某次,某开发者执行完npm install -g @vue/cli@5.0.8,再运行vue create demo创建项目,进入项目后执行npm run serve,却报出:
Error: Cannot find module '@vue/cli-service' Require stack: - /Users/xxx/demo/node_modules/vue-cli-service/bin/vue-cli-service.js他反复检查package.json,确认"devDependencies": { "@vue/cli-service": "^5.0.8" }存在,node_modules里也有该包。问题出在哪?
答案是:他本地的npm配置中启用了--no-bin-links(为适配某些 Windows 权限策略),导致vue-cli-service的二进制入口文件node_modules/.bin/vue-cli-service没有被正确创建为符号链接,而是一个空文件。全局安装的@vue/cli在create阶段并不校验这个链接是否存在,直到npm run serve时才暴露。
注意:这种错误不会出现在
vue create过程中,因为创建阶段只依赖@vue/cli本身;但一旦项目生成完成,后续所有开发命令都强依赖node_modules/.bin/下的可执行链接。全局安装无法保证项目级依赖的完整性。
2.3 全局安装的适用边界与致命限制
我整理了一份“全局安装自查清单”,如果你的答案中有任意一项为“是”,请立刻放弃此方式:
| 检查项 | 说明 | 是否适用 |
|---|---|---|
| 你是否在公司内网环境,且 npm registry 被强制代理到私有源? | 私有源可能未同步@vue/cli最新版,或存在 tarball 校验失败 | ❌ 不适用 |
| 你的项目是否要求 CI/CD 流水线每次构建都使用固定 CLI 版本? | 全局安装版本无法被package-lock.json锁定,CI 机器上版本不可控 | ❌ 不适用 |
| 你是否同时维护多个 Vue 项目,其中部分用 Vue 2(需 CLI 4.x),部分用 Vue 3(需 CLI 5.x)? | 全局只能存在一个vue命令,无法按项目切换 CLI 版本 | ❌ 不适用 |
你是否需要在项目中自定义vue.config.js并调试 CLI 内部插件链? | 全局 CLI 的源码路径与项目node_modules分离,断点调试路径混乱 | ❌ 不适用 |
唯一推荐使用全局安装的场景:你在写一篇面向零基础学员的 Vue 入门课,需要让学员在 5 分钟内看到vue create成功输出,并强调“先跑起来再深究”。此时牺牲确定性,换取教学流畅度,是合理权衡。
2.4 实操优化:如何让全局安装更可控?
如果你仍需全局安装(例如团队内部已统一流水线规范),请务必执行以下加固步骤:
锁定 Node.js 和 npm 版本:
使用.nvmrc文件声明最低要求:18.17.0并在 CI 脚本中加入:
nvm install && nvm use npm install -g npm@9.6.7强制清除旧缓存与冲突链接:
# 彻底卸载旧版 npm uninstall -g @vue/cli @vue/cli-service # 清理 npm 缓存(关键!很多报错源于缓存损坏) npm cache clean --force # 重新安装(显式指定 registry,避免镜像源差异) npm install -g @vue/cli@5.0.8 --registry https://registry.npmjs.org/验证安装完整性:
运行以下命令,确保所有子命令均可访问:vue --version # 应输出 5.0.8 vue create --help # 应列出完整参数 vue invoke --help # 验证插件系统可用
经验心得:我在某高校前端实训中发现,约 37% 的“安装失败”案例,根源是学生电脑上残留了 cnpm 或 yarn 的全局 bin 目录,导致
PATH中存在多个vue可执行文件。解决方法不是重装,而是执行which vue查看实际调用路径,再用ls -la $(which vue)确认符号链接指向。这是比重装更高效的排错起点。
3. 局部安装 + npx:现代前端工程化的事实标准
3.1 为什么 npx 正在取代全局安装?
npx是 npm 5.2+ 内置的工具,它的设计哲学非常清晰:“按需加载,用完即走”。当你执行:
npx @vue/cli@5.0.8 create my-projectnpx 会做以下事情:
- 检查本地
node_modules/.bin/下是否存在@vue/cli对应的可执行文件; - 若不存在,则临时下载
@vue/cli@5.0.8到~/.npm/_npx/缓存目录(注意:不是全局 node_modules); - 将该缓存包的
bin目录加入临时PATH,执行create命令; - 命令结束后,不留下任何全局污染——
vue命令依然不可用,npm list -g里也看不到它。
这意味着:你不需要提前安装任何东西,只要有一台能联网的 Node.js 环境,就能随时创建 Vue 项目。更重要的是,npx默认优先使用package.json中声明的版本(如果存在),其次才是缓存或远程下载,天然支持版本锁定。
3.2 从零开始的完整流程(含错误预防)
我们以一个真实协作场景为例:某团队要求所有新项目必须使用@vue/cli@5.0.8,且禁止开发者本地全局安装 CLI。
步骤 1:初始化空项目目录
mkdir my-vue-app && cd my-vue-app步骤 2:用 npx 创建项目(关键:显式指定版本号)
npx @vue/cli@5.0.8 create . --default --packageManager npm.表示在当前目录创建(避免嵌套子目录);--default跳过交互式选项,使用默认 preset(Vue 3 + Babel + ESLint);--packageManager npm明确指定包管理器,防止 npx 自动选择 yarn(某些环境下会)。
注意:不要省略
@5.0.8。如果不加版本号,npx 会拉取最新版(当前是 5.0.9),而团队规范要求 5.0.8。版本号是确定性的第一道防线。
步骤 3:验证项目内 CLI 版本
进入项目后,执行:
npm list @vue/cli # 输出:my-vue-app@0.1.0 /path/to/my-vue-app # └── @vue/cli@5.0.8这证明@vue/cli已作为devDependencies被写入package.json,且package-lock.json已锁定其完整依赖树。
步骤 4:后续开发全部走npx或npm run
# 启动开发服务器(等价于运行 node_modules/.bin/vue-cli-service serve) npx vue-cli-service serve # 构建生产包 npx vue-cli-service build # 执行 lint(无需全局 eslint) npx vue-cli-service lint你会发现,这些命令之所以能运行,是因为vue-cli-service的二进制文件已在node_modules/.bin/中生成,而npx会自动查找该目录。
3.3 npx 的隐藏能力:离线模式与自定义 preset
npx远不止“临时下载”这么简单。它有两个被严重低估的能力:
▶ 离线模式(Offline Mode)
当你的网络受限(如飞机上、内网隔离区),只要之前用过该版本,npx 会自动从~/.npm/_npx/缓存中加载:
# 首次联网执行(会缓存) npx @vue/cli@5.0.8 create offline-demo # 断网后再次执行(直接读缓存) npx @vue/cli@5.0.8 create offline-demo-2缓存路径可通过npm config get cache查看,默认为~/.npm。
▶ 直接运行自定义 preset
Vue CLI 支持从 Git 仓库加载 preset。npx 让这一操作变得极其轻量:
npx @vue/cli@5.0.8 create my-app --preset git@github.com:my-org/vue-preset.gitnpx 会自动克隆仓库、解析preset.json,并执行其中定义的插件安装逻辑。全程无需手动git clone、npm install,极大简化定制化脚手架分发。
3.4 常见陷阱与绕过方案
尽管 npx 很强大,但在实际落地中仍有几个高频问题:
❗ 问题1:npx找不到vue-cli-service,报错 “command not found”
原因:npx默认只查找node_modules/.bin/和~/.npm/_npx/,但vue-cli-service是@vue/cli-service包的二进制入口,而@vue/cli-service是作为devDependencies安装在项目里的,其bin文件必然存在于node_modules/.bin/。所以此报错几乎 100% 源于:
- 项目尚未执行
npm install(create命令只生成文件,不自动安装依赖); - 或
package.json中漏写了"devDependencies": { "@vue/cli-service": "..." }。
解决方案:
# 确保先安装依赖 npm install # 再执行服务命令 npx vue-cli-service serve❗ 问题2:npx执行缓慢,首次耗时超过 30 秒
原因:npx 每次都会检查远程 registry 是否有更新版本(即使你指定了@5.0.8),这个网络请求在弱网下会超时阻塞。
解决方案:添加--no-install参数跳过远程检查:
npx --no-install @vue/cli@5.0.8 create my-app⚠️ 注意:仅在你确定本地缓存已有该版本时使用,否则会报错“not found”。
❗ 问题3:CI/CD 中npx命令不稳定,偶发失败
原因:CI 环境通常禁用网络,或使用精简 Docker 镜像,缺少~/.npm/_npx/目录权限。
终极方案:在 CI 脚本中,改用npx的“预安装”模式:
# 先确保 @vue/cli 在 node_modules 中(通过 npm install) npm install --save-dev @vue/cli@5.0.8 # 再用 npx 调用(此时 npx 直接走 node_modules/.bin,不联网) npx vue-cli-service build这相当于“局部安装 + npx 调用”的混合体,兼顾确定性与简洁性。
实战技巧:我在某电商中台项目中,将
npx vue-cli-service封装成 Makefile 命令,开发者只需make dev即可启动。Makefile 内容如下:dev: @echo "🚀 Starting Vue development server..." @npx vue-cli-service serve --open build: @echo "📦 Building for production..." @npx vue-cli-service build --mode production这样既隐藏了技术细节,又保证了所有成员执行完全一致的命令。
4. 项目级依赖 + 脚本封装:企业级工程治理的终极形态
4.1 当“安装方式”变成“架构决策”
前面两种方式,本质仍是“工具使用”。而第三种方式,是把@vue/cli当作项目基础设施的一部分来管理。它不再是一个外部命令,而是你工程体系中的一个可编程组件。
核心思想是:将 CLI 的所有能力,通过package.json的scripts字段进行声明式封装,并配合vue.config.js做深度行为定制。
我们来看一个典型的企业级package.json片段:
{ "name": "enterprise-vue-app", "version": "1.0.0", "devDependencies": { "@vue/cli": "5.0.8", "@vue/cli-service": "5.0.8", "@vue/compiler-sfc": "3.3.4", "vue-template-compiler": "2.7.14" }, "scripts": { "dev": "vue-cli-service serve --mode development", "dev:mock": "cross-env VUE_APP_MOCK=true vue-cli-service serve", "build": "vue-cli-service build --mode production", "build:staging": "vue-cli-service build --mode staging", "lint": "vue-cli-service lint --fix", "test:unit": "vue-cli-service test:unit --watch", "prepare": "husky install" } }这里的关键变化在于:
@vue/cli和@vue/cli-service被明确列为devDependencies,版本号严格锁定;- 所有 CLI 命令都被包装进
scripts,开发者只需npm run dev,无需记忆npx或vue命令; --mode参数将构建行为与环境变量解耦,vue.config.js中可据此动态配置publicPath、proxy等;prepare脚本自动初始化 husky,将 lint 和 test 集成到 Git Hooks,实现“提交即校验”。
4.2 vue.config.js:CLI 行为的“操作系统内核”
vue.config.js是 Vue CLI 的灵魂文件。它不是一个配置清单,而是一个 Node.js 模块,导出一个函数,接收config对象并返回修改后的config。这意味着你可以:
- 动态读取环境变量,调整 Webpack 配置;
- 注册自定义 Webpack 插件(如
CompressionPlugin); - 覆盖 Vue CLI 默认的
resolve.alias; - 甚至拦截
vue-cli-service的生命周期钩子(如configureWebpack、chainWebpack)。
举个真实案例:某金融项目要求所有静态资源必须上传至 CDN,且 HTML 中的<script>标签需添加integrity属性。我们通过vue.config.js实现:
const { defineConfig } = require('@vue/cli-service') const HtmlWebpackPlugin = require('html-webpack-plugin') const { createHash } = require('crypto') module.exports = defineConfig({ configureWebpack: { plugins: [ new HtmlWebpackPlugin({ // 自定义 template,注入 integrity hash template: 'public/index.html', minify: { removeComments: true, collapseWhitespace: true } }) ] }, chainWebpack: config => { // 为所有 JS/CSS 文件生成 SRI hash config.plugin('html').tap(args => { const htmlPlugin = args[0] htmlPlugin.integrity = true return args }) // 修改 publicPath 为 CDN 地址 if (process.env.NODE_ENV === 'production') { config.plugin('html').tap(args => { args[0].cdn = { js: ['https://cdn.example.com/vue/5.0.8/vue.runtime.esm-bundler.js'] } return args }) } } })这段代码之所以能生效,是因为@vue/cli-service在启动时会require并执行vue.config.js,并将返回的配置合并到 Webpack 实例中。没有vue.config.js,CLI 就只是一个黑盒;有了它,你就拥有了对整个构建流程的完全控制权。
4.3 如何调试 CLI 内部行为?——从源码级理解
当vue.config.js无法满足需求时(比如需要修改 CLI 启动逻辑本身),你需要深入 CLI 源码。以下是高效调试路径:
- 定位 CLI 入口:
@vue/cli的主命令vue指向packages/@vue/cli/bin/vue.js; - 找到
create命令实现:在packages/@vue/cli/lib/create.js中,核心逻辑是调用createApp函数; - 查看
createApp的参数处理:它会读取--preset、--default等参数,并决定是否下载 preset、是否运行git init; - 调试技巧:在
create.js开头插入debugger,然后用 VS Code 的 Node.js 调试模式运行:
VS Code 会自动连接并停在node --inspect-brk ./node_modules/@vue/cli/bin/vue.js create my-app --defaultdebugger处,你可以查看options对象的完整结构、preset的解析结果等。
经验心得:我在为某政务系统定制 CLI 时,需要在
create后自动执行git commit -m "init: created by enterprise-cli"。通过阅读create.js源码,我发现它在run()函数末尾调用了await runGit(),于是我在自己的 preset 的generator/index.js中覆盖了complete钩子:module.exports = { complete: async (data, { cwd }) => { await execa('git', ['commit', '-m', '"init: created by enterprise-cli"'], { cwd }) } }这种深度定制,只有将 CLI 视为项目级依赖才能实现。
4.4 企业级最佳实践:Preset + Plugin 的组合拳
Vue CLI 的真正威力,在于它的可扩展架构。一个完整的工程治理方案,通常包含三层:
| 层级 | 组件 | 作用 | 示例 |
|---|---|---|---|
| Preset(脚手架模板) | preset.json+generator/ | 定义项目初始结构、依赖列表、配置文件骨架 | {"useConfigFiles": true, "plugins": {"@vue/cli-plugin-eslint": {...}}} |
| Plugin(功能插件) | @vue/cli-plugin-* | 提供特定能力(如 PWA、TypeScript、Unit Test) | @vue/cli-plugin-unit-jest |
| Generator(代码生成器) | generator/index.js | 在create过程中动态生成文件、修改配置 | 自动生成 API service 层、Mock 数据目录 |
我们以某中台系统的 preset 为例,其preset.json关键片段:
{ "useConfigFiles": true, "cssPreprocessor": "scss", "plugins": { "@vue/cli-plugin-babel": {}, "@vue/cli-plugin-eslint": { "config": "standard", "lintOn": ["save"] }, "@vue/cli-plugin-router": { "historyMode": true }, "my-org/vue-cli-plugin-cdn": { "cdnHost": "https://cdn.myorg.com" } } }其中my-org/vue-cli-plugin-cdn是团队自研插件,它会在vue.config.js中注入 CDN 配置,并在build阶段自动上传 assets 到对象存储。这个插件被发布到公司私有 npm 仓库,所有项目通过 preset 声明即可复用,无需每个项目单独配置。
提示:自研插件的
index.js必须导出一个函数,接收api对象(提供api.chainWebpack、api.configureWebpack等方法)和options(来自 preset 的配置)。这是 Vue CLI 插件机制的核心契约。
5. 三种方式的决策树与迁移路线图
5.1 如何选择?一张表终结所有纠结
我把选择逻辑浓缩为一张决策表,覆盖 95% 的真实场景:
| 你的核心诉求 | 推荐方式 | 关键理由 | 风险提示 |
|---|---|---|---|
| 个人学习、快速验证想法、写博客 Demo | 全局安装 | 命令最短,心智负担最小,vue create一气呵成 | 版本漂移风险高,团队协作时易引发“在我机器上是好的”类问题 |
| 团队协作项目、CI/CD 流水线、多项目并行开发 | 局部安装 + npx | 版本由package.json锁定,npx确保命令一致性,无全局污染 | 首次执行略慢(需下载),需教育团队成员习惯npx命令 |
| 中大型企业应用、需深度定制构建流程、有统一工程规范 | 项目级依赖 + 脚本封装 | 完全掌控 CLI 行为,可集成自研插件、定制 preset、对接内部基建(如 CDN、监控 SDK) | 初期投入成本高,需专人维护 preset 和插件,对团队前端工程化能力有要求 |
注意:这不是非此即彼的选择,而是演进路线。绝大多数团队都从“全局安装”起步,经历“npx 过渡期”,最终走向“项目级治理”。关键是要识别当前阶段的瓶颈。
5.2 从全局安装平滑迁移到项目级依赖
如果你的项目目前是全局安装,想升级到更健壮的模式,以下是零风险迁移步骤:
✅ 步骤 1:检查当前 CLI 版本与项目兼容性
# 在项目根目录执行 vue --version # 记录全局版本,如 4.5.15 npm list @vue/cli # 查看项目内是否已存在,如无则为空✅ 步骤 2:将 CLI 显式安装为项目依赖
# 安装最新稳定版(或指定版本) npm install --save-dev @vue/cli@5.0.8 # 同时安装配套服务 npm install --save-dev @vue/cli-service@5.0.8✅ 步骤 3:更新package.json脚本
将原有scripts中的vue命令替换为vue-cli-service:
// 替换前 "scripts": { "serve": "vue serve", "build": "vue build" } // 替换后 "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" }提示:
vue serve是 CLI 4 的遗留命令,CLI 5 已废弃,必须替换为vue-cli-service。
✅ 步骤 4:生成vue.config.js并迁移配置
如果项目已有vue.config.js,保留;如果没有,运行:
npx @vue/cli-service inspect > webpack.config.js该命令会输出当前 Webpack 配置快照,帮助你理解默认行为。然后创建空vue.config.js:
module.exports = {}后续再根据需要逐步添加配置。
✅ 步骤 5:验证并清理全局 CLI(可选)
# 验证新命令是否可用 npm run serve # 确认无误后,卸载全局 CLI(避免混淆) npm uninstall -g @vue/cli整个过程可在 10 分钟内完成,且不影响现有开发流程。迁移完成后,你的项目就拥有了版本确定性、可复现性、以及面向未来的可扩展性。
5.3 一个被忽略的真相:CLI 版本与 Vue 版本的语义化对齐
最后分享一个多数人不知道的底层规则:Vue CLI 的主版本号,与 Vue 的主版本号是语义化对齐的。
@vue/cli@4.x→ 官方支持 Vue 2(兼容 Vue 3 的实验性支持);@vue/cli@5.x→ 官方支持 Vue 3(兼容 Vue 2 的实验性支持);@vue/cli@6.x(规划中)→ 将聚焦 Vue 3.3+ 新特性(如<script setup>的深度优化、响应式语法糖增强)。
这意味着:当你升级 Vue 版本时,CLI 版本也必须同步升级。例如,将 Vue 从 2.7 升级到 3.3,不升级 CLI 到 5.x,会导致defineProps、defineEmits等新语法无法被正确解析,构建时报错Unknown context property。
因此,在package.json中,你应该这样声明依赖:
"dependencies": { "vue": "^3.3.4" }, "devDependencies": { "@vue/cli": "^5.0.8", "@vue/cli-service": "^5.0.8" }而不是将 CLI 版本锁死为5.0.8。^符号允许自动升级到5.x的最新补丁版(如5.0.9),同时阻止升级到6.0.0(重大变更)。这是保障长期可维护性的最小代价。
我在某政府项目审计中发现,一个上线三年的系统,
@vue/cli仍停留在4.5.13,而 Vue 已升级到3.2.45。结果是v-model在<input>上的行为异常,排查三天才发现是 CLI 版本不匹配导致的编译器降级。教训是:CLI 不是“装一次就不管”的工具,它是 Vue 生态的编译器,必须与 Vue 版本共进退。
6. 总结:安装方式的背后,是你对工程确定性的理解深度
写完这篇长文,我想回到开头那个团队协作事故。三位新人的问题,表面是“安装命令记错了”,深层是“对前端工程化中‘确定性’的理解缺失”。
- 全局安装,提供的是命令行层面的便利性,代价是牺牲版本确定性;
- npx 方式,提供的是执行层面的确定性,代价是增加一次网络请求(可缓存);
- 项目级依赖,提供的是工程全生命周期的确定性,代价是前期配置成本。
没有绝对正确的选择,只有最适合当下阶段的权衡。但有一点是普适的:当你开始思考“为什么这个命令要这么写”,而不是“复制粘贴能不能跑”,你就已经走在了专业前端工程师的路上。
最后分享一个小技巧:在你的终端~/.zshrc或~/.bashrc中,添加一行别名:
alias vuec='npx @vue/cli@5.0.8'以后创建项目只需vuec create my-app,既保留了 npx 的确定性,又缩短了输入长度。这种微小的自动化,正是工程师日常中对效率的温柔坚持。
至于你此刻正面对的项目,不妨打开终端,先执行npm list @vue/cli,看看它现在是什么状态。然后问自己一句:这个状态,是否真的匹配你接下来三个月的开发节奏?