Npmスクリプトで環境変数を動的に設定したいと思います。
Windowsで開発していて、サーバーがUnixベースであるため、_cross-env
_を使用しています。環境変数を現在の日付(new Date()
)で初期化して、_create-react-app
_でアクセスしてレンダリングできるようにします。
これは機能します(ハードコードされた文字列):
_"scripts": {
"start": "cross-env-Shell REACT_APP_BUILD_DATE=\"currentDate\" react-scripts-ts start",
}
_
明らかに、currentDate
は文字列ではなく、次の式の結果である必要があります:new Date()
。
どうすればそれを達成できますか?言い換えると、通常のJavaScriptを評価し、その結果をnpmスクリプトで使用するにはどうすればよいでしょうか。それともこれは不可能ですか?
呼び出されたスクリプトに環境変数を渡すために、単純なノードスクリプトを使用しています。 child_process.execSyncを使用します。
// File name: ./build.js
/* eslint-env node */
const execSync = require('child_process').execSync;
const env = Object.create(process.env);
env.REACT_APP_BUILD_DATE= Date.now();
console.log('Used env variables: ' + JSON.stringify(env));
console.log('Run command: react-scripts start');
execSync('react-scripts-ts start', { env: env, stdio: 'inherit' });
Package.jsonスクリプトのstartコマンドを更新します。このような:
"scripts": {"start": "node ./build.js"}
念のため、現在、次のアプローチを使用しています。package.jsonのカスタムプロパティに現在の日付を書き込み、package.json
をインポートしてアプリでその値を読み取ります。
package.json
"scripts": {
"start": "react-scripts-ts start",
"build": "node ./update-packagejson.js && react-scripts-ts build"
}
pdate-packagejson.js
const fs = require("fs");
const filePath = "./package.json";
const packageJson = JSON.parse(fs.readFileSync(filePath).toString());
packageJson.ngrvd.buildDate = new Date().toUTCString();
fs.writeFileSync(filePath, JSON.stringify(packageJson, null, 2));
コンポーネント
import { ngrvd, version } from "../../package.json";
// ...
private static getAppInfo(): string {
const buildDate = process.env.NODE_ENV === "development" ? new Date() : ngrvd.buildDate;
return "Version " + version + " - Built " + moment(buildDate).fromNow();
}
これはどのような環境でも機能し、シンプルで理解しやすく、他の情報も含めるように拡張できます。開発モードでは、毎回ローカルで変更されるのを防ぐためにpackage.json
に書き込みません。
この特定のケースでは、JavaScriptの代わりにShellコマンドを使用する方がよいため、次のようになります。
"scripts": {
"start": "cross-env-Shell REACT_APP_BUILD_DATE=$(date '+%F %H:%M:%S') react-scripts-ts start",
}
私はあなたのためにそれを行うカスタムjavascriptスクリプトを作成します:
execute.js
var spawn = require('child_process').spawn;
// because first arg will actually be something like "./execute.js"
// this is the "regular javascript" you want to evaluate
var arg1 = process.argv[1];
// so lets eval it
var res = eval(arg1);
// this is the remaining args, that is the command you want to run (and its args)
var command = process.argv[2];
var commandArgs = process.argv.slice(3);
// if arg1 evaluation resulted in a value, append this value to the list of args
if (res) {
commandArgs.Push(res);
}
// execute the command
var prc = spawn(command, commandArgs);
スクリプト定義は次のようになります。
"scripts": {
"start": "cross-env-Shell ./execute.js \"process.env.REACT_APP_BUILD_DATE = new Date();\" react-scripts-ts start",
}
または同様のもの。
これはテストされていませんが、「通常のJavaScriptを評価し、その結果をnpmスクリプト」のソリューションで開始する必要があります。
ただし、環境変数に日付を設定するだけの場合は、@ bredikhinのソリューションの方が適しています。
環境変数を処理するための代替ソリューション
プロジェクトのルートにある.env
fileに(手動またはプログラムで)書き込む余裕がある場合は、 dotenv を使用して環境変数にデータを入力できます( から) dotenv ドキュメント):
// Usage
// As early as possible in your application, require and configure dotenv.
require('dotenv').config()
/* Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE. For example:
DB_Host=localhost
DB_USER=root
DB_PASS=s1mpl3
That's it.
process.env now has the keys and values you defined in your .env file.
*/
const db = require('db');
db.connect({
Host: process.env.DB_Host,
username: process.env.DB_USER,
password: process.env.DB_PASS
});