NestJS项目npm脚本执行含动态环境变量的启动命令失败求助
NestJS项目npm脚本执行含动态环境变量的启动命令失败求助
兄弟,我之前也踩过这个一模一样的坑!你的问题根源在于cross-env的默认行为不支持shell命令替换,再加上npm脚本在Windows下默认用cmd.exe执行,不兼容bash风格的$(...)语法,导致命令被错误拆分,才会出现'-p' is not recognized的诡异报错。
下面给你两个靠谱的解决方案,按需选择:
方案一:改用cross-env-shell(最简单快速)
cross-env本身是直接启动子进程,不会通过系统shell解析命令,所以$(...)这种变量替换语法根本无法生效。而cross-env-shell会通过系统默认shell来执行整个命令,就能正确解析这些替换逻辑了。
步骤:
- 先安装配套的
cross-env-shell:
npm install cross-env-shell --save-dev
- 修改你的npm脚本:
"scripts": { "start:dev": "cross-env-shell \"VERSION=$(node -p 'require(\\'./package.json\\').version') LAST_COMMIT_DATE=$(git log -1 --format=%cd) NODE_ENV=development nest start --watch\"" }
如果你的终端支持简化引号写法,也可以改成更清爽的版本:
"scripts": { "start:dev": "cross-env-shell VERSION=$(node -p \"require('./package.json').version\") LAST_COMMIT_DATE=$(git log -1 --format=%cd) NODE_ENV=development nest start --watch" }
方案二:用Node.js脚本封装(最稳定跨平台)
如果不想依赖shell的语法差异,直接写个小Node脚本处理环境变量,再启动Nest项目,这种方式完全跨平台,不会有Windows/Linux的语法冲突,后续扩展也更方便。
步骤:
- 在项目根目录创建
start-dev.js文件:
const { execSync, spawn } = require('child_process'); const packageJson = require('./package.json'); // 读取package.json的版本号 const appVersion = packageJson.version; // 获取最后一次Git提交日期(trim去掉多余的换行符) const lastCommitDate = execSync('git log -1 --format=%cd', { encoding: 'utf8' }).trim(); // 设置环境变量 process.env.VERSION = appVersion; process.env.LAST_COMMIT_DATE = lastCommitDate; process.env.NODE_ENV = 'development'; // 启动Nest项目,继承当前控制台的输入输出 spawn('nest', ['start', '--watch'], { stdio: 'inherit' });
- 修改package.json的脚本:
"scripts": { "start:dev": "node start-dev.js" }
这种方式不需要额外安装cross-env系列包,逻辑也更清晰,后续要加其他动态变量直接在脚本里加就行。
为什么原来的命令会报错?
你直接在终端执行时,是通过bash/zsh(Linux)或者Git Bash/WSL(Windows)来解析命令,$(...)会被正确替换成对应的值。但放到npm脚本后,Windows下默认用cmd.exe执行,它完全不认识$(...)语法,再加上cross-env直接把$(node -p ...)当成了命令的一部分,导致系统误以为-p是要执行的独立命令,自然会报“找不到命令”的错误。
备注:内容来源于stack exchange,提问作者lavrent
相关产品推荐
相关产品推荐

