方案一:自定义执行脚本
实现思路
nestjs
本身是可以读取到根目录的.env
文件的,以此为突破口,在.env
文件中添加环境变量NODE_ENV=development
- 当我们执行
npm run start:dev
时,给.env
文件中写入NODE_ENV=development
- 当我们执行
npm run build
时,给.env
文件中写入NODE_ENV=production
- 通过编写一个
node
脚本文件,当执行npm脚本
的时候也顺便执行这个node脚本
并传参,在node脚本
文件中操作.env
文件
新建node脚本
src
下新建 script/NpmScript.ts
文件
/**
* 执行npm run 执行的脚本
* */
import * as fs from "fs";
import * as path from "path";
// 获取根目录的路径
const rootPath = path.join(__dirname,"../../");
// 获取根目录的目录名
const rootDir = fs.readdirSync(rootPath);
/**
* 获取脚本参数,处理 npm脚本 传给 node脚本 的参数,处理为一个对象
* { env:"development" }
* */
const scriptParams:ScriptParams = process.argv.filter(e => (/.+=.+/g).test(e))
.reduce((a,b) => {
a[b.split("=")[0]] = b.split("=")[1];
return a;
},{});
/**
* 脚本方法类文件
* 可定义多个方法
* */
export class RunScriptFn {
// 创建并写入env文件,如果已经存在则删除,如果传递又env参数则创建并写入
static createEnv(env:Env=scriptParams.env){
if(rootDir.includes(".env")) fs.unlinkSync(path.join(rootPath,".env"));
if(env) fs.writeFileSync(path.join(rootPath,".env"),`NODE_ENV=${env}`);
}
}
// 当执行node脚本的时候,自动执行此方法
(async function main() {
// 通过fn参数来决定执行RunScriptFn类中的方法,不传仅执行createEnv方法
const fns = scriptParams?.fn?.split(",") || ["createEnv"];
for(const fn of fns){
await RunScriptFn[fn]();
}
})()
// node脚本参数
interface ScriptParams {
// 设置的环境变量
env?:Env;
// 执行的Fn类下的方法,多个用英文逗号分割
fn?:string;
}
// 环境变量
type Env = "development" | "production";
执行node脚本
通过改写 package.json
中的 script
属性来执行 node脚本
。
这里以 build
和 start:dev
为例
"scripts": {
// build的时候应该是先打包,再写入.env文件
"build": "nest build && ts-node src/script/NpmScript env=production",
// start:dev 的时候应该是先写入.env,再执行nest start
"start:dev": "ts-node src/script/NpmScript env=development && nest start --watch",
},
node脚本
的参数详见 ScriptParams
例:
ts-node src/script/NpmScript env=production fn=createEnv,xxx,ooo